学习Rust的第28天:rm in Rust

2024-05-06 13:12
文章标签 rust 学习 28 rm

本文主要是介绍学习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 包含以下方法的实现块:

  1. new() : To instantiate out struct
    new() :实例化结构体
  2. help() : To print the help text if arguments contain --help
    help() :如果参数包含 --help 则打印帮助文本
  3. not_enough_arguments() : If the user has not supplied enough arguments
    not_enough_arguments() :如果用户没有提供足够的参数
  4. rm_dir_all(path) : To remove the specified folder
    rm_dir_all(path) : 删除指定文件夹
  5. 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 function new, which takes a reference to a vector of strings (args) and returns a Config instance with args assigned to files.
    Config 结构有一个关联的函数 new ,它引用字符串向量 ( args ) 并返回 Config 实例将 args 分配给 files 。
  • There are some helper functions like not_enough_arguments() and help() which provide error messages and usage information, respectively.
    有一些辅助函数,例如 not_enough_arguments() 和 help() ,它们分别提供错误消息和使用信息。
  • The run() method of Config 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 type io::Result<()>.
    函数 rm_dir_all 获取对表示文件或目录路径的字符串 ( src ) 的引用,并返回 io::Result<()> 类型的结果。
  • It first creates a Path instance from the provided src string using Path::new(src).
    它首先使用 Path::new(src) 从提供的 src 字符串创建一个 Path 实例。
  • Then, it creates a PathBuf instance from the Path using to_path_buf(), storing it in src_path_buffer.
    然后,它使用 to_path_buf() 从 Path 创建一个 PathBuf 实例,并将其存储在 src_path_buffer 中。
  • It checks if the path represented by src_path_buffer is a directory using is_dir(). If it is a directory, it removes the directory and all its contents recursively using fs::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的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/964448

相关文章

Java进阶学习之如何开启远程调式

《Java进阶学习之如何开启远程调式》Java开发中的远程调试是一项至关重要的技能,特别是在处理生产环境的问题或者协作开发时,:本文主要介绍Java进阶学习之如何开启远程调式的相关资料,需要的朋友... 目录概述Java远程调试的开启与底层原理开启Java远程调试底层原理JVM参数总结&nbsMbKKXJx

Rust中的注释使用解读

《Rust中的注释使用解读》本文介绍了Rust中的行注释、块注释和文档注释的使用方法,通过示例展示了如何在实际代码中应用这些注释,以提高代码的可读性和可维护性... 目录Rust 中的注释使用指南1. 行注释示例:行注释2. 块注释示例:块注释3. 文档注释示例:文档注释4. 综合示例总结Rust 中的注释

Rust格式化输出方式总结

《Rust格式化输出方式总结》Rust提供了强大的格式化输出功能,通过std::fmt模块和相关的宏来实现,主要的输出宏包括println!和format!,它们支持多种格式化占位符,如{}、{:?}... 目录Rust格式化输出方式基本的格式化输出格式化占位符Format 特性总结Rust格式化输出方式

Rust中的Drop特性之解读自动化资源清理的魔法

《Rust中的Drop特性之解读自动化资源清理的魔法》Rust通过Drop特性实现了自动清理机制,确保资源在对象超出作用域时自动释放,避免了手动管理资源时可能出现的内存泄漏或双重释放问题,智能指针如B... 目录自动清理机制:Rust 的析构函数提前释放资源:std::mem::drop android的妙

Rust中的BoxT之堆上的数据与递归类型详解

《Rust中的BoxT之堆上的数据与递归类型详解》本文介绍了Rust中的BoxT类型,包括其在堆与栈之间的内存分配,性能优势,以及如何利用BoxT来实现递归类型和处理大小未知类型,通过BoxT,Rus... 目录1. Box<T> 的基础知识1.1 堆与栈的分工1.2 性能优势2.1 递归类型的问题2.2

Java深度学习库DJL实现Python的NumPy方式

《Java深度学习库DJL实现Python的NumPy方式》本文介绍了DJL库的背景和基本功能,包括NDArray的创建、数学运算、数据获取和设置等,同时,还展示了如何使用NDArray进行数据预处理... 目录1 NDArray 的背景介绍1.1 架构2 JavaDJL使用2.1 安装DJL2.2 基本操

在Rust中要用Struct和Enum组织数据的原因解析

《在Rust中要用Struct和Enum组织数据的原因解析》在Rust中,Struct和Enum是组织数据的核心工具,Struct用于将相关字段封装为单一实体,便于管理和扩展,Enum用于明确定义所有... 目录为什么在Rust中要用Struct和Enum组织数据?一、使用struct组织数据:将相关字段绑

浅析Rust多线程中如何安全的使用变量

《浅析Rust多线程中如何安全的使用变量》这篇文章主要为大家详细介绍了Rust如何在线程的闭包中安全的使用变量,包括共享变量和修改变量,文中的示例代码讲解详细,有需要的小伙伴可以参考下... 目录1. 向线程传递变量2. 多线程共享变量引用3. 多线程中修改变量4. 总结在Rust语言中,一个既引人入胜又可

Rust 数据类型详解

《Rust数据类型详解》本文介绍了Rust编程语言中的标量类型和复合类型,标量类型包括整数、浮点数、布尔和字符,而复合类型则包括元组和数组,标量类型用于表示单个值,具有不同的表示和范围,本文介绍的非... 目录一、标量类型(Scalar Types)1. 整数类型(Integer Types)1.1 整数字

Rust中的Option枚举快速入门教程

《Rust中的Option枚举快速入门教程》Rust中的Option枚举用于表示可能不存在的值,提供了多种方法来处理这些值,避免了空指针异常,文章介绍了Option的定义、常见方法、使用场景以及注意事... 目录引言Option介绍Option的常见方法Option使用场景场景一:函数返回可能不存在的值场景