学习Rust的第25天:Rust中的mkdir

为了实现重建 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
让我们为 helpnot_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 a Result 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 the mkdir module (defined in lib.rs) using use mkdir::Config.
    使用 use mkdir::Configmkdir 模块(在 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 using Config::new(&args).
    使用 Config::new(&args) 构造一个 Config 实例 ( config ) 以及其余参数。
  • Calls the run method on the config instance to execute the program's logic.
    调用 config 实例上的 run 方法来执行程序的逻辑。
相关推荐
蚂蚁背大象4 小时前
Rust 所有权系统是为了解决什么问题
后端·rust
布列瑟农的星空5 小时前
前端都能看懂的rust入门教程(五)—— 所有权
rust
Java水解1 天前
Rust嵌入式开发实战——从ARM裸机编程到RTOS应用
后端·rust
Pomelo_刘金1 天前
Rust:所有权系统
rust
Ranger09291 天前
鸿蒙开发新范式:Gpui
rust·harmonyos
DongLi014 天前
rustlings 学习笔记 -- exercises/05_vecs
rust
郑州光合科技余经理5 天前
代码展示:PHP搭建海外版外卖系统源码解析
java·开发语言·前端·后端·系统架构·uni-app·php
feifeigo1235 天前
matlab画图工具
开发语言·matlab
西岸行者5 天前
学习笔记:SKILLS 能帮助更好的vibe coding
笔记·学习
dustcell.5 天前
haproxy七层代理
java·开发语言·前端