学习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 方法来执行程序的逻辑。
相关推荐
qq_172805592 分钟前
RUST学习教程-安装教程
开发语言·学习·rust·安装
wjs20249 分钟前
MongoDB 更新集合名
开发语言
monkey_meng13 分钟前
【遵守孤儿规则的External trait pattern】
开发语言·后端·rust
一只小小汤圆17 分钟前
opencascade源码学习之BRepOffsetAPI包 -BRepOffsetAPI_DraftAngle
c++·学习·opencascade
虾球xz25 分钟前
游戏引擎学习第20天
前端·学习·游戏引擎
LateBloomer77734 分钟前
FreeRTOS——信号量
笔记·stm32·学习·freertos
legend_jz37 分钟前
【Linux】线程控制
linux·服务器·开发语言·c++·笔记·学习·学习方法
Komorebi.py38 分钟前
【Linux】-学习笔记04
linux·笔记·学习
tangliang_cn1 小时前
java入门 自定义springboot starter
java·开发语言·spring boot
程序猿阿伟1 小时前
《智能指针频繁创建销毁:程序性能的“隐形杀手”》
java·开发语言·前端