本文主要是介绍学习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
Config
struct has an associated functionnew
, which takes a reference to a vector of strings (args
) and returns aConfig
instance withargs
assigned 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 ofConfig
is responsible for executing the desired functionality based on the provided arguments.Config
的run()
方法负责根据提供的参数执行所需的功能。 - It checks if there are enough arguments, prints help information if
--help
is 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_all
takes 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
Path
instance from the providedsrc
string usingPath::new(src)
.
它首先使用Path::new(src)
从提供的src
字符串创建一个Path
实例。 - Then, it creates a
PathBuf
instance from thePath
usingto_path_buf()
, storing it insrc_path_buffer
.
然后,它使用to_path_buf()
从Path
创建一个PathBuf
实例,并将其存储在src_path_buffer
中。 - It checks if the path represented by
src_path_buffer
is 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的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!