Rust >> Operating Files and Folders
Table of Contents
This tutorial will explain how to use Rust to operate files and folders. (Reading a file, Writing to a file, Appending content to an existing file, Write a file with a specified encoding, Copying a file, Moving/Renaming a file, Removing a file, Creating a directory, Creating directories recursively, Moving/Renaming a directory, Removing a directory (and all its contents)).
In Rust, you can use the std::fs module to perform various operations on files and directories. Here are some examples of how you can use this module:
Reading a file
use std::fs;
use std::io::prelude::*;
fn main() -> std::io::Result<()> {
let mut file = fs::File::open("test.txt")?;
let mut contents = String::new();
file.read_to_string(&mut contents)?;
println!("{}", contents);
Ok(())
}
Writing to a file
use std::fs;
use std::io::prelude::*;
fn main() -> std::io::Result<()> {
let mut file = fs::File::create("test.txt")?;
file.write_all(b"Hello, world!")?;
Ok(())
}
Appending content to an existing file
To append content to a file in Rust, you can use the append method of the std::fs::OpenOptions struct. This method will open the file in append mode, which means that any data written to the file will be added to the end of the file.
Here’s an example of how you can use append to append content to a file:
use std::fs;
use std::io::prelude::*;
fn main() -> std::io::Result<()> {
let mut file = fs::OpenOptions::new()
.append(true)
.open("test.txt")?;
file.write_all(b"Hello, world!")?;
Ok(())
}
This will open the file test.txt in append mode, and write the string “Hello, world!” to the end of the file.
If you want to append a string to the file, you can use the write_all method and pass it a string slice. For example:
file.write_all(b"Hello, world!")?;
Or you can use the writeln method to write a string and a newline character:
file.writeln("Hello, world!")?;
Write a file with a specified encoding
To write a file with a specified encoding in Rust, you can use a library that provides support for different encodings. For example, you can use the encoding_rs crate to write a file with a specified encoding.
Here’s an example of how you can use the encoding_rs crate to write a file with the UTF-8 encoding:
use encoding_rs::UTF_8;
use std::fs;
use std::io::prelude::*;
fn main() -> std::io::Result<()> {
let mut file = fs::File::create("test.txt")?;
file.write_all(UTF_8.encode("Hello, world!"))?;
Ok(())
}
This will create a new file test.txt and write the string “Hello, world!" to the file using the UTF-8 encoding.
If you want to use a different encoding, you can use a different encoding from the encoding_rs crate. For example, to use the ASCII encoding, you can use the ASCII constant:
use encoding_rs::ASCII;
use std::fs;
use std::io::prelude::*;
fn main() -> std::io::Result<()> {
let mut file = fs::File::create("test.txt")?;
file.write_all(ASCII.encode("Hello, world!"))?;
Ok(())
}
Copying a file
use std::fs;
fn main() -> std::io::Result<()> {
fs::copy("test.txt", "test_copy.txt")?;
Ok(())
}
Moving/Renaming a file
To move a file in Rust, you can use the rename function from the std::fs module. This function will move the file from the source path to the destination path. If the destination path is a directory, the file will be moved into that directory. If the destination path is a file, the file will be renamed.
Here’s an example of how you can use rename to move a file:
use std::fs;
fn main() -> std::io::Result<()> {
fs::rename("old_name.txt", "new_name.txt")?;
Ok(())
}
This will rename the file old_name.txt to new_name.txt.
If you want to move the file to a different directory, you can specify the full path to the destination file. For example:
use std::fs;
fn main() -> std::io::Result<()> {
fs::rename("old_name.txt", "path/to/new/dir/new_name.txt")?;
Ok(())
}
This will move the file old_name.txt to the path/to/new/dir directory and rename it to new_name.txt.
Removing a file
use std::fs;
fn main() -> std::io::Result<()> {
fs::remove_file("test.txt")?;
Ok(())
}
Creating a directory
use std::fs;
fn main() -> std::io::Result<()> {
fs::create_dir("test_dir")?;
Ok(())
}
Creating directories recursively
To create directories recursively in Rust, you can use the create_dir_all function from the std::fs module. This function will create all the intermediate directories in the specified path, if they don’t already exist.
Here’s an example of how you can use create_dir_all:
use std::fs;
fn main() -> std::io::Result<()> {
fs::create_dir_all("path/to/new/dir")?;
Ok(())
}
This will create the path, path/to, path/to/new, and path/to/new/dir directories, if they don’t already exist.
Moving/Renaming a directory
To move a directory in Rust, you can use the rename function from the std::fs module. This function will move the directory from the source path to the destination path. If the destination path is a directory, the directory will be moved into that directory. If the destination path is a file, the function will return an error.
Here’s an example of how you can use rename to move a directory:
use std::fs;
fn main() -> std::io::Result<()> {
fs::rename("old_dir", "new_dir")?;
Ok(())
}
This will rename the directory old_dir to new_dir.
If you want to move the directory to a different location, you can specify the full path to the destination directory. For example:
use std::fs;
fn main() -> std::io::Result<()> {
fs::rename("old_dir", "path/to/new/location/new_dir")?;
Ok(())
}
This will move the directory old_dir to the path/to/new/location directory and rename it to new_dir.
Note that the rename function will not move the directory and its contents recursively. If you want to move a directory and all its contents, you will need to write code to do that manually. You can do this by reading the contents of the directory (using the read_dir function), and then recursively moving each file and subdirectory.
Here’s an example of how you can move a directory and its contents recursively in Rust:
use std::fs;
use std::path::Path;
fn move_dir_recursive(src: &Path, dst: &Path) -> std::io::Result<()> {
if src.is_dir() {
fs::create_dir_all(dst)?;
for entry in src.read_dir()? {
let entry = entry?;
let src_path = entry.path();
let dst_path = dst.join(entry.file_name());
if src_path.is_dir() {
move_dir_recursive(&src_path, &dst_path)?;
} else {
fs::rename(&src_path, &dst_path)?;
}
}
} else {
fs::rename(src, dst)?;
}
fs::remove_dir_all(src)?;
Ok(())
}
fn main() -> std::io::Result<()> {
let src = Path::new("old_dir");
let dst = Path::new("new_dir");
move_dir_recursive(src, dst)?;
Ok(())
}
This code defines a helper function move_dir_recursive that takes a source and destination path, and moves the contents of the source directory (including all subdirectories and files) to the destination.
The function first creates the destination directory if it doesn’t already exist. Then it reads the contents of the source directory using read_dir, and for each entry, it checks if it is a directory or a file. If it is a directory, the function calls itself recursively to move the contents of that directory. If it is a file, it uses the rename function to move the file.
Finally, the function removes the source directory using remove_dir_all.
You can use this function like this:
move_dir_recursive(Path::new("old_dir"), Path::new("new_dir"))?;
This will move the contents of the old_dir directory (including all subdirectories and files) to the new_dir directory.
Removing a directory (and all its contents)
use std::fs;
fn main() -> std::io::Result<()> {
fs::remove_dir_all("test_dir")?;
Ok(())
}