本文主要是介绍学习Rust的第28天:rm in Rust,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
过去几天以来,我们一直在 Rust 中重新创建 GNU 核心实用程序的基本功能,今天我们构建了另一个工具,用于从文件系统中删除文件和目录。
您可以在此处查看github存储库:shafinmurani/gnu-core-utils-rust (github.com)

Pseudo Code 伪代码
function remove(path)->result{fs::remove_dir_all(src)?;Ok(())
}args = command_line_arguments
remove the first element of the args vector
if args.length == 0 {print error_message
}
else if args.contains("--help") {print help_message
} else {for path in args {result = remove(path);error handling}
} Setup 设置
So let’s create a struct an implementation block containing the following methods:
因此,让我们创建一个 struct 包含以下方法的实现块:
- new() : To instantiate out struct
new() :实例化结构体 - help() : To print the help text if arguments contain
--help
help() :如果参数包含--help则打印帮助文本 - not_enough_arguments() : If the user has not supplied enough arguments
not_enough_arguments() :如果用户没有提供足够的参数 - rm_dir_all(path) : To remove the specified folder
rm_dir_all(path) : 删除指定文件夹 - run() : To carry out logic and error handling, calling the other functions..
run() :执行逻辑和错误处理,调用其他函数。
We will do all of this in a lib.rs file and then call our run function in a binary crate to create and executable file
我们将在 lib.rs 文件中完成所有这些操作,然后在二进制包中调用 run 函数来创建可执行文件
pub struct Config<'a> {pub files: &'a Vec<String>,
}impl Config<'_> {pub fn new(args: &Vec<String>) -> Config{Config{files: args}}fn not_enough_arguments(){eprintln!("rm: missing operand");eprintln!("For help use: rm --help");}fn help() {eprintln!("This is a cheap little clone of the rm utility in the GNU core utilities, the catch is that I made it in rust, check out more of my work at medium: https://shafinmurani.medium.com");eprintln!("This is recursive by default so dont worry about anything, just run it :D");eprintln!("To use this util: rm path1 path2 ... pathN");}fn rm_dir_all(){//We'll leave this function empty and come back to it later on}pub fn run(&self){if self.files.len() == 0 {Self::not_enough_arguments();} else if self.files.contains(&String::from("--help")) {Self::help();} else {for path in self.files {// We will call the rm_dir_all() function here// error handling here}}}
} Okay looks simple enough? let’s break it down and understand it
好吧,看起来够简单吧?让我们分解并理解它
- This code defines a Rust struct named
Config, which holds a reference to a vector of strings (files).
此代码定义了一个名为Config的 Rust 结构体,它保存对字符串向量 (files) 的引用。 - The
Configstruct has an associated functionnew, which takes a reference to a vector of strings (args) and returns aConfiginstance withargsassigned tofiles.Config结构有一个关联的函数new,它引用字符串向量 (args) 并返回Config实例将args分配给files。 - There are some helper functions like
not_enough_arguments()andhelp()which provide error messages and usage information, respectively.
有一些辅助函数,例如not_enough_arguments()和help(),它们分别提供错误消息和使用信息。 - The
run()method ofConfigis responsible for executing the desired functionality based on the provided arguments.Config的run()方法负责根据提供的参数执行所需的功能。 - It checks if there are enough arguments, prints help information if
--helpis provided, and otherwise iterates over the provided paths to perform the remove operations (which is currently left unimplemented).
它检查是否有足够的参数,如果提供了--help则打印帮助信息,否则迭代提供的路径以执行删除操作(当前未实现)。
Implementing the remove function
实现删除功能
To implement this, we’ll go with a really easy to use function of the std::fs crate, std::fs::remove_dir_all if the specified path is a directory and std::fs::remove_file if the specified path is a file
为了实现这一点,我们将使用 std::fs 箱的一个非常易于使用的功能,如果指定的路径是目录,则使用 std::fs::remove_dir_all ;如果指定的路径是目录,则使用 std::fs::remove_file 指定路径是一个文件
You can check out the documentations of these function here:
您可以在此处查看这些函数的文档:remove_dir_all in std::fs - Rust (rust-lang.org)
Let’s build the function and break it down
让我们构建函数并分解它
//we will also import the following modules
use std::path::Path;
use std::{fs, io}fn rm_dir_all(src: &String) -> io::Result<()> {let src_path = Path::new(src);let src_path_buffer = src_path.to_path_buf();if src_path_buffer.is_dir() {fs::remove_dir_all(src)?;Ok(())} else {fs::remove_file(src)?;Ok(())}
} - The function
rm_dir_alltakes a reference to a string (src) representing a file or directory path, and returns a result of typeio::Result<()>.
函数rm_dir_all获取对表示文件或目录路径的字符串 (src) 的引用,并返回io::Result<()>类型的结果。 - It first creates a
Pathinstance from the providedsrcstring usingPath::new(src).
它首先使用Path::new(src)从提供的src字符串创建一个Path实例。 - Then, it creates a
PathBufinstance from thePathusingto_path_buf(), storing it insrc_path_buffer.
然后,它使用to_path_buf()从Path创建一个PathBuf实例,并将其存储在src_path_buffer中。 - It checks if the path represented by
src_path_bufferis a directory usingis_dir(). If it is a directory, it removes the directory and all its contents recursively usingfs::remove_dir_all(src)?.
它使用is_dir()检查src_path_buffer表示的路径是否是目录。如果它是一个目录,它会使用fs::remove_dir_all(src)?递归地删除该目录及其所有内容。 - If the path is not a directory (presumably a file), it attempts to remove the file using
fs::remove_file(src)?.
如果路径不是目录(可能是文件),它会尝试使用fs::remove_file(src)?删除文件。 - It returns
Ok(())if the removal operation is successful, otherwise propagates any encountered IO errors.
如果删除操作成功,它将返回Ok(()),否则传播任何遇到的 IO 错误。
Error Handling 错误处理
Let’s call the rm_dir_all() function in our run() function and handle the propogated errors…
让我们在 run() 函数中调用 rm_dir_all() 函数并处理传播的错误......
use std::path::Path;
use std::{fs, io};pub struct Config<'a> {pub files: &'a Vec<String>,
}impl Config<'_> {pub fn new(args: &Vec<String>) -> Config{Config{files: args}}fn not_enough_arguments(){eprintln!("rm: missing operand");eprintln!("For help use: rm --help");}fn help() {eprintln!("This is a cheap little clone of the rm utility in the GNU core utilities, the catch is that I made it in rust, check out more of my work at medium: https://shafinmurani.medium.com");eprintln!("This is recursive by default so dont worry about anything, just run it :D");eprintln!("To use this util: rm path1 path2 ... pathN");}fn rm_dir_all(src: &String) -> io::Result<()> {let src_path = Path::new(src);let src_path_buffer = src_path.to_path_buf();if src_path_buffer.is_dir() {fs::remove_dir_all(src)?;Ok(())} else {fs::remove_file(src)?;Ok(())}}pub fn run(&self){if self.files.len() == 0 {Self::not_enough_arguments();} else if self.files.contains(&String::from("--help")) {Self::help();} else {for path in self.files {let result = Self::rm_dir_all(path);match result {Ok(()) => {},Err(e) => eprintln!("Application Error: `{}` {}" path, e),};}}}
} Binary Crate 二进制箱
That’s all for the library crate, now let’s get to our main.rs file
这就是库箱的全部内容,现在让我们进入 main.rs 文件
use rm::Config;
use std::env;fn main(){let mut args: Vec<String> = env::args().collect();args.remove(0);let config = Config::new(&args);config.run();
} And that’s all we have to do, let’s test it out and see how it works.
这就是我们所要做的,让我们测试一下,看看它是如何工作的。
Execution 执行
That is what the tree of my /tmp directory looks like, I compiled the rust code to a binary using cargo build --release
这就是我的 /tmp 目录树的样子,我使用 cargo build --release 将 Rust 代码编译为二进制文件
.
├── rm
├── test_dir
│ ├── test_dir_in_dir
│ └── test_file_in_dir
└── test_file To delete the test_dir we can run the following command
要删除 test_dir 我们可以运行以下命令
# ./rm test_dir/ The tree looks like this rn
这棵树看起来像这样
.
├── rm
└── test_file Removing the test_file 删除 test_file
./rm test_dir/ tree: 树:
.
└── rm 这篇关于学习Rust的第28天:rm in Rust的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!