为了实现重建 GNU 核心实用程序的崇高目标,今天的工具是 mkdir 我们用来在 Linux 上创建目录的工具。让我们开始吧。

Pseudo Code 伪代码
ba
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 directory_name in args {
create_directory(directory_name)
}
}
Okay that looks simple enough let's start with new cargo library crate and create a simple struct and a new function
好吧,看起来很简单,让我们从新的货物库箱开始,创建一个简单的结构体和一个 new 函数
ba
pub struct Config<'a>{
pub dir_names: &'a Vec<String>
}
impl Config<'_>{
pub fn new(args: &Vec<String>) -> Config {
Config {dir_names: args}
}
}
Let's make our work a little bit easier by creating private functions for help and not_enough_arguments
让我们为 help 和 not_enough_arguments 创建私有函数,让我们的工作变得更容易一些
ba
impl Config<'_>{
pub fn new(args: &Vec<String>) -> Config{
Config { dir_names: args }
}
fn not_enough_arguments(){
eprintln!("mkdir: missing operand");
eprintln!("For help use: mkdir --help");
}
fn help(){
eprintln!("This is a cheap little clone of the mkdir 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!("To use this util: mkdir folder_name1 folder_name2 ... folder_nameN");
}
}
Now that the basics are setup, we will create a binary crate, main.rs
现在基础知识已经设置完毕,我们将创建一个二进制板条箱, main.rs
ba
use mkdir::Config; //use your cratename::structName here
use std::env;
fn main(){
let mut args: Vec<String> = env::args.collect();
args.remove(0);
let config == Config::new(&args);
}
This will instantiate our Config struct, now getting to the important part...
这将实例化我们的 Config 结构,现在进入重要部分......
To create a directory, there are two functions in the fs crate , fs::create_dir() and fs::create_dir_all() . I will leave you with the task to find their differences and why we will be using create_dir_all(). Here's a resource for you to research it create_dir() and create_dir_all()
要创建目录, fs crate 中有两个函数, fs::create_dir() 和 fs::create_dir_all() 。我将留给您找出它们的差异以及为什么我们将使用 create_dir_all() 的任务。这里有一个资源供您研究 create_dir() 和 create_dir_all()
Let's create a function which will create a directory in out impl block...
让我们创建一个函数,它将在 impl 块中创建一个目录......
ba
fn create_dir(dir: String) -> std::io::Result<()> {
fs::create_dir_all(dir)?;
Ok(())
}
It returns a Result indicating success or failure, As of now here's what our lib.rs file looks like
它返回一个 Result 指示成功或失败,到目前为止,这是我们的 lib.rs 文件的样子
ba
pub struct Config<'a>{
pub dir_names: &'a Vec<String>
}
impl Config<'_>{
pub fn new(args: &Vec<String>) -> Config{
Config { dir_names: args }
}
fn not_enough_arguments(){
eprintln!("mkdir: missing operand");
eprintln!("For help use: mkdir --help");
}
fn help(){
eprintln!("This is a cheap little clone of the mkdir 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!("To use this util: mkdir folder_name1 folder_name2 ... folder_nameN");
}
fn create_dir(dir: String) -> std::io::Result<()> {
fs::create_dir_all(dir)?;
Ok(())
}
}
Now we have everything we'll need to make a directory, so let's make one?
现在我们已经拥有了制作目录所需的一切,那么让我们制作一个目录吧?
We will create a run function, which takes a reference to self and call our private function in there according to the conditons we specified in out pseudo code
我们将创建一个 run 函数,它引用 self 并根据我们在伪代码中指定的条件调用我们的私有函数
ba
pub fn run(&self){
if self.dir_names.len() == 0 {
Self.not_enough_arguments();
} else if self.dir_names.contains(&String::from("--help")) {
Self.help();
} else {
for dir in self.dir_names {
let result = Self::create_dir(dir.to_string());
}
}
}
This program does work but we don't really have any error handling taking place here...
该程序确实有效,但我们实际上没有进行任何错误处理......
Let's fix that 让我们解决这个问题
ba
pub fn run(&self){
if self.dir_names.len() == 0 {
Self.not_enough_arguments();
} else if self.dir_names.contains(&String::from("--help")) {
Self.help();
} else {
for dir in self.dir_names {
let result = Self::create_dir(dir.to_string());
match result {
Ok(()) => {},
Err(e) => {
eprintln!("{}",e)
},
};
}
}
}
Now we can call the run function in our main.rs file...
现在我们可以在 main.rs 文件中调用 run 函数......
ba
use mkdir::Config;
use std::env;
fn main() {
let mut args: Vec<String> = env::args().collect();
args.remove(0);
let config = Config::new(&args);
config.run();
}
GitHub 仓库:shafinmurani/gnu-core-utils-rust (github.com)
Summary 概括
Lib.rs 库
- Defines a Rust library module.
定义 Rust 库模块。 - Contains the
Configstruct and its implementation.
包含Config结构及其实现。 Configstruct:Config结构:- Holds a reference to a vector of strings (
dir_names) representing directory names to be created.
保存对表示要创建的目录名称的字符串向量 (dir_names) 的引用。
Implementation block impl Config<'_>:
实现块 impl Config<'_> :
newfunction:new功能:- Constructs a new
Configinstance, taking a reference to a vector of strings (args) as input.
构造一个新的Config实例,将对字符串向量 (args) 的引用作为输入。
not_enough_arguments function: not_enough_arguments 功能:
- Prints an error message to standard error if no directory names are provided as arguments.
如果没有提供目录名称作为参数,则将错误消息打印到标准错误。
help function: help 功能:
- Prints a help message to standard error explaining how to use the program.
将帮助消息打印到标准错误,解释如何使用该程序。
create_dir function: create_dir 功能:
- Attempts to create a directory specified by the input string using the
fs::create_dir_allfunction from the standard library. It returns aResultindicating success or failure.
尝试使用标准库中的fs::create_dir_all函数创建由输入字符串指定的目录。它返回一个Result指示成功或失败。
run function: run 功能:
- Executes the logic of the program.
执行程序的逻辑。 - If no directory names are provided, it prints a "missing operand" error message.
如果未提供目录名称,则会打印"缺少操作数"错误消息。 - If the
--helpargument is provided, it prints the help message.
如果提供了--help参数,它将打印帮助消息。 - Otherwise, it iterates through the provided directory names, attempting to create each directory and printing any encountered errors.
否则,它会迭代提供的目录名称,尝试创建每个目录并打印遇到的任何错误。
Main.rs
- Defines the entry point of the program.
定义程序的入口点。 - Imports the
Configstruct from themkdirmodule (defined inlib.rs) usinguse mkdir::Config.
使用use mkdir::Config从mkdir模块(在lib.rs中定义)导入Config结构体。 - Imports the
envmodule from the standard library, used to access command-line arguments.
从标准库导入env模块,用于访问命令行参数。 mainfunction:main功能:- Retrieves command-line arguments using
env::args()and collects them into a vector (args).
使用env::args()检索命令行参数并将它们收集到向量中 (args)。 - Removes the first argument, which is the name of the program itself, using
args.remove(0).
使用args.remove(0)删除第一个参数,即程序本身的名称。 - Constructs a
Configinstance (config) with the remaining arguments usingConfig::new(&args).
使用Config::new(&args)构造一个Config实例 (config) 以及其余参数。 - Calls the
runmethod on theconfiginstance to execute the program's logic.
调用config实例上的run方法来执行程序的逻辑。