学习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 方法来执行程序的逻辑。
相关推荐
微爱帮监所写信寄信1 天前
微爱帮监狱寄信写信小程序信件内容实时保存技术方案
java·服务器·开发语言·前端·小程序
笔夏1 天前
【安卓学习之myt】adb常用命令
android·学习·adb
李少兄1 天前
时间戳转换工具
开发语言·javascript·工具
ss2731 天前
CompletionService:Java并发工具包
java·开发语言·算法
额呃呃1 天前
select和poll之间的性能对比
开发语言·算法
智航GIS1 天前
7.2 Try Except语句
开发语言·python
星轨初途1 天前
C++ string 类详解:概念、常用操作与实践(算法竞赛类)
开发语言·c++·经验分享·笔记·算法
二进制_博客1 天前
JWT权限认证快速入门
java·开发语言·jwt
d111111111d1 天前
配置STM32F411CEU6的系统时钟-避免芯片内核锁死
笔记·stm32·单片机·嵌入式硬件·学习
程序员佳佳1 天前
026年AI开发实战:从GPT-5.2到Gemini-3,如何构建下一代企业级Agent架构?
开发语言·python·gpt·重构·api·ai写作·agi