为了实现重建 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
Config
struct and its implementation.
包含Config
结构及其实现。 Config
struct: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<'_>
:
new
function:new
功能:- Constructs a new
Config
instance, 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_all
function from the standard library. It returns aResult
indicating 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
--help
argument 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
Config
struct from themkdir
module (defined inlib.rs
) usinguse mkdir::Config
.
使用use mkdir::Config
从mkdir
模块(在lib.rs
中定义)导入Config
结构体。 - Imports the
env
module from the standard library, used to access command-line arguments.
从标准库导入env
模块,用于访问命令行参数。 main
function: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
Config
instance (config
) with the remaining arguments usingConfig::new(&args)
.
使用Config::new(&args)
构造一个Config
实例 (config
) 以及其余参数。 - Calls the
run
method on theconfig
instance to execute the program's logic.
调用config
实例上的run
方法来执行程序的逻辑。