学习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 方法来执行程序的逻辑。
相关推荐
艾莉丝努力练剑2 小时前
【AI接入大模型SDK】ChatSDK示例验证
人工智能·学习·面试·大模型·sdk
葡萄成熟时 !7 小时前
JAVA 常用API学习笔记
java·笔记·学习
剩下了什么8 小时前
float32 与 float64 精度陷阱:如何在 Go 中避免错误使用
开发语言·后端·golang
指尖时光.8 小时前
Three.js 超全入门综合案例
开发语言·javascript·ecmascript
暴力求解9 小时前
Linux网络---传输层协议TCP(二)
linux·服务器·开发语言·网络·tcp/ip
吴声子夜歌9 小时前
Java面试题——基础(一)
java·开发语言
别动我齐刘海9 小时前
机器人运动控制学习2——基础进阶
c++·人工智能·神经网络·学习·目标检测·机器学习·机器人
小庞在加油9 小时前
WinDbg实战:QT/跨平台项目死锁与无响应问题排查指南
开发语言·qt·windbg·工具
Vae_Mars10 小时前
C#中的delegate委托
开发语言·c#
一直走下去-明10 小时前
简单的http抓包解包完整代码
开发语言·python