Opérations sur le système de fichiers en Rust

RustRustBeginner
Pratiquer maintenant

This tutorial is from open-source community. Access the source code

💡 Ce tutoriel est traduit par l'IA à partir de la version anglaise. Pour voir la version originale, vous pouvez cliquer ici

Introduction

Dans ce laboratoire, le module std::fs de Rust est présenté, qui fournit des fonctions pour les opérations sur le système de fichiers. Le laboratoire fournit des exemples de diverses opérations sur le système de fichiers, notamment la création de répertoires, la création de fichiers, la lecture du contenu des fichiers, la création de liens symboliques, la liste du contenu d'un répertoire, la suppression de fichiers et la suppression de répertoires. Les extraits de code montrent comment effectuer ces opérations à l'aide des fonctions du module std::fs, et la sortie attendue pour chaque opération est fournie. De plus, une implémentation alternative de la fonction cat utilisant la notation ? pour la gestion des erreurs est mentionnée.

Note : Si le laboratoire ne spécifie pas de nom de fichier, vous pouvez utiliser n'importe quel nom de fichier que vous voulez. Par exemple, vous pouvez utiliser main.rs, le compiler et l'exécuter avec rustc main.rs &&./main.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL rust(("Rust")) -.-> rust/DataTypesGroup(["Data Types"]) rust(("Rust")) -.-> rust/FunctionsandClosuresGroup(["Functions and Closures"]) rust(("Rust")) -.-> rust/AdvancedTopicsGroup(["Advanced Topics"]) rust(("Rust")) -.-> rust/BasicConceptsGroup(["Basic Concepts"]) rust(("Rust")) -.-> rust/ControlStructuresGroup(["Control Structures"]) rust(("Rust")) -.-> rust/DataStructuresandEnumsGroup(["Data Structures and Enums"]) rust/BasicConceptsGroup -.-> rust/variable_declarations("Variable Declarations") rust/BasicConceptsGroup -.-> rust/mutable_variables("Mutable Variables") rust/DataTypesGroup -.-> rust/boolean_type("Boolean Type") rust/DataTypesGroup -.-> rust/string_type("String Type") rust/ControlStructuresGroup -.-> rust/for_loop("for Loop") rust/FunctionsandClosuresGroup -.-> rust/function_syntax("Function Syntax") rust/FunctionsandClosuresGroup -.-> rust/expressions_statements("Expressions and Statements") rust/DataStructuresandEnumsGroup -.-> rust/method_syntax("Method Syntax") rust/AdvancedTopicsGroup -.-> rust/operator_overloading("Traits for Operator Overloading") subgraph Lab Skills rust/variable_declarations -.-> lab-99277{{"Opérations sur le système de fichiers en Rust"}} rust/mutable_variables -.-> lab-99277{{"Opérations sur le système de fichiers en Rust"}} rust/boolean_type -.-> lab-99277{{"Opérations sur le système de fichiers en Rust"}} rust/string_type -.-> lab-99277{{"Opérations sur le système de fichiers en Rust"}} rust/for_loop -.-> lab-99277{{"Opérations sur le système de fichiers en Rust"}} rust/function_syntax -.-> lab-99277{{"Opérations sur le système de fichiers en Rust"}} rust/expressions_statements -.-> lab-99277{{"Opérations sur le système de fichiers en Rust"}} rust/method_syntax -.-> lab-99277{{"Opérations sur le système de fichiers en Rust"}} rust/operator_overloading -.-> lab-99277{{"Opérations sur le système de fichiers en Rust"}} end

Opérations sur le système de fichiers

Le module std::fs contient plusieurs fonctions qui traitent le système de fichiers.

use std::fs;
use std::fs::{File, OpenOptions};
use std::io;
use std::io::prelude::*;
use std::os::unix;
use std::path::Path;

// Une implémentation simple de `% cat path`
fn cat(path: &Path) -> io::Result<String> {
    let mut f = File::open(path)?;
    let mut s = String::new();
    match f.read_to_string(&mut s) {
        Ok(_) => Ok(s),
        Err(e) => Err(e),
    }
}

// Une implémentation simple de `% echo s > path`
fn echo(s: &str, path: &Path) -> io::Result<()> {
    let mut f = File::create(path)?;

    f.write_all(s.as_bytes())
}

// Une implémentation simple de `% touch path` (ignore les fichiers existants)
fn touch(path: &Path) -> io::Result<()> {
    match OpenOptions::new().create(true).write(true).open(path) {
        Ok(_) => Ok(()),
        Err(e) => Err(e),
    }
}

fn main() {
    println!("`mkdir a`");
    // Crée un répertoire, renvoie `io::Result<()>`
    match fs::create_dir("a") {
        Err(why) => println!("! {:?}", why.kind()),
        Ok(_) => {},
    }

    println!("`echo hello > a/b.txt`");
    // Le match précédent peut être simplifié en utilisant la méthode `unwrap_or_else`
    echo("hello", &Path::new("a/b.txt")).unwrap_or_else(|why| {
        println!("! {:?}", why.kind());
    });

    println!("`mkdir -p a/c/d`");
    // Crée récursivement un répertoire, renvoie `io::Result<()>`
    fs::create_dir_all("a/c/d").unwrap_or_else(|why| {
        println!("! {:?}", why.kind());
    });

    println!("`touch a/c/e.txt`");
    touch(&Path::new("a/c/e.txt")).unwrap_or_else(|why| {
        println!("! {:?}", why.kind());
    });

    println!("`ln -s../b.txt a/c/b.txt`");
    // Crée un lien symbolique, renvoie `io::Result<()>`
    if cfg!(target_family = "unix") {
        unix::fs::symlink("../b.txt", "a/c/b.txt").unwrap_or_else(|why| {
            println!("! {:?}", why.kind());
        });
    }

    println!("`cat a/c/b.txt`");
    match cat(&Path::new("a/c/b.txt")) {
        Err(why) => println!("! {:?}", why.kind()),
        Ok(s) => println!("> {}", s),
    }

    println!("`ls a`");
    // Lit le contenu d'un répertoire, renvoie `io::Result<Vec<Path>>`
    match fs::read_dir("a") {
        Err(why) => println!("! {:?}", why.kind()),
        Ok(paths) => for path in paths {
            println!("> {:?}", path.unwrap().path());
        },
    }

    println!("`rm a/c/e.txt`");
    // Supprime un fichier, renvoie `io::Result<()>`
    fs::remove_file("a/c/e.txt").unwrap_or_else(|why| {
        println!("! {:?}", why.kind());
    });

    println!("`rmdir a/c/d`");
    // Supprime un répertoire vide, renvoie `io::Result<()>`
    fs::remove_dir("a/c/d").unwrap_or_else(|why| {
        println!("! {:?}", why.kind());
    });
}

Voici la sortie réussie attendue :

$ rustc fs.rs && ./fs
$(mkdir a)
$(echo hello > a/b.txt)
$(mkdir -p a/c/d)
$(touch a/c/e.txt)
$(ln -s../b.txt a/c/b.txt)
$(cat a/c/b.txt)
> hello
$(ls a)
> "a/b.txt"
> "a/c"
$(rm a/c/e.txt)
$(rmdir a/c/d)

Et l'état final du répertoire a est :

$ tree a
a
|-- b.txt
`-- c
    `-- b.txt ->../b.txt

1 répertoire, 2 fichiers

Une manière alternative de définir la fonction cat est avec la notation ? :

fn cat(path: &Path) -> io::Result<String> {
    let mut f = File::open(path)?;
    let mut s = String::new();
    f.read_to_string(&mut s)?;
    Ok(s)
}

Sommaire

Félicitations ! Vous avez terminé le laboratoire sur les opérations sur le système de fichiers. Vous pouvez pratiquer d'autres laboratoires sur LabEx pour améliorer vos compétences.