ファイルシステムとのやり取り - Rust By Example
Description: Rust by Example (RBE) is a collection of runnable examples that illustrate various Rust concepts and standard libraries.

## Keyboard shortcuts

Press `←` or `→` to navigate between chapters

Press `S` or `/` to search in the book

Press `?` to show this help

Press `Esc` to hide this help

# ファイルシステムとのやり取り

`std::fs`モジュールはファイルシステムとやり取りするための関数をいくつか持っています。

    use std::fs;
    use std::fs::{File, OpenOptions};
    use std::io;
    use std::io::prelude::*;
    #[cfg(target_family = "unix")]
    use std::os::unix;
    #[cfg(target_family = "windows")]
    use std::os::windows;
    use std::path::Path;

    // `% 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),
        }
    }

    // `% echo s > path`の簡単な実装
    fn echo(s: &str, path: &Path) -> io::Result<()> {
        let mut f = File::create(path)?;

        f.write_all(s.as_bytes())
    }

    // `% touch path`の簡単な実装（すでにファイルが存在しても無視します。）
    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`");
        // ディレクトリを作成します。返り値は`io::Result<()>`。
        match fs::create_dir("a") {
            Err(why) => println!("! {:?}", why.kind()),
            Ok(_) => {},
        }

        println!("`echo hello > a/b.txt`");
        // 上のmatchは`unwrap_or_else`をメソッドを用いて簡略化できます。
        echo("hello", &Path::new("a/b.txt")).unwrap_or_else(|why| {
            println!("! {:?}", why.kind());
        });

        println!("`mkdir -p a/c/d`");
        // 再帰的にディレクトリを作成します。返り値は`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`");
        // シンボリックリンクを作成、返り値は`io::Result<()>`。
        #[cfg(target_family = "unix")] {
            unix::fs::symlink("../b.txt", "a/c/b.txt").unwrap_or_else(|why| {
                println!("! {:?}", why.kind());
            });
        }
        #[cfg(target_family = "windows")] {
            windows::fs::symlink_file("../b.txt", "a/c/b.txt").unwrap_or_else(|why| {
                println!("! {:?}", why.to_string());
            });
        }

        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`");
        // ディレクトリの内容を読み込みます。返り値は`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`");
        // ファイルを削除。返り値は`io::Result<()>`。
        fs::remove_file("a/c/e.txt").unwrap_or_else(|why| {
            println!("! {:?}", why.kind());
        });

        println!("`rmdir a/c/d`");
        // 空のディレクトリを削除。返り値は`io::Result<()>`。
        fs::remove_dir("a/c/d").unwrap_or_else(|why| {
            println!("! {:?}", why.kind());
        });
    }

以下が成功時に期待されるアウトプットです。

    $ 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`

最終的な`a`ディレクトリの状態は以下です。

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

    1 directory, 2 files

An alternative way to define the function `cat` is with `?` 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)
    }

### 参照

`cfg!`