summaryrefslogtreecommitdiffstats
path: root/src/doc/rust-by-example/src/std_misc/fs.md
diff options
context:
space:
mode:
Diffstat (limited to 'src/doc/rust-by-example/src/std_misc/fs.md')
-rw-r--r--src/doc/rust-by-example/src/std_misc/fs.md146
1 files changed, 146 insertions, 0 deletions
diff --git a/src/doc/rust-by-example/src/std_misc/fs.md b/src/doc/rust-by-example/src/std_misc/fs.md
new file mode 100644
index 000000000..48e4d4d66
--- /dev/null
+++ b/src/doc/rust-by-example/src/std_misc/fs.md
@@ -0,0 +1,146 @@
+# Filesystem Operations
+
+The `std::fs` module contains several functions that deal with the filesystem.
+
+```rust,ignore
+use std::fs;
+use std::fs::{File, OpenOptions};
+use std::io;
+use std::io::prelude::*;
+use std::os::unix;
+use std::path::Path;
+
+// A simple implementation of `% 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),
+ }
+}
+
+// A simple implementation of `% echo s > path`
+fn echo(s: &str, path: &Path) -> io::Result<()> {
+ let mut f = File::create(path)?;
+
+ f.write_all(s.as_bytes())
+}
+
+// A simple implementation of `% touch path` (ignores existing files)
+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`");
+ // Create a directory, returns `io::Result<()>`
+ match fs::create_dir("a") {
+ Err(why) => println!("! {:?}", why.kind()),
+ Ok(_) => {},
+ }
+
+ println!("`echo hello > a/b.txt`");
+ // The previous match can be simplified using the `unwrap_or_else` method
+ echo("hello", &Path::new("a/b.txt")).unwrap_or_else(|why| {
+ println!("! {:?}", why.kind());
+ });
+
+ println!("`mkdir -p a/c/d`");
+ // Recursively create a directory, returns `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`");
+ // Create a symbolic link, returns `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`");
+ // Read the contents of a directory, returns `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`");
+ // Remove a file, returns `io::Result<()>`
+ fs::remove_file("a/c/e.txt").unwrap_or_else(|why| {
+ println!("! {:?}", why.kind());
+ });
+
+ println!("`rmdir a/c/d`");
+ // Remove an empty directory, returns `io::Result<()>`
+ fs::remove_dir("a/c/d").unwrap_or_else(|why| {
+ println!("! {:?}", why.kind());
+ });
+}
+
+```
+
+Here's the expected successful output:
+
+```shell
+$ 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`
+```
+
+And the final state of the `a` directory is:
+
+```shell
+$ 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:
+
+```rust,ignore
+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)
+}
+```
+
+### See also:
+
+[`cfg!`][cfg]
+
+[cfg]: ../attribute/cfg.md