I want to call some shell commands from Rust. In Python it is as easy as:
import os
os.system("ls -alh")
In Rust, we can use the std::process::Command
function.
ls
example
use std::process::Command;
use std::str;
fn main() {
// ls
let output = Command::new("ls")
.arg("-alh")
.output()
.unwrap();
let output = str::from_utf8(&output.stdout).unwrap();
println!("{}", output);
}
Run it we can get something like:
total 8
drwxr-xr-x 3 0xbf staff 96B Dec 10 22:23 .
drwxr-xr-x 8 0xbf staff 256B Dec 10 22:23 ..
-rw-r--r-- 1 0xbf staff 288B Dec 10 22:27 main.rs
cp
example
Suppose we have folder source
and target
, under source
there is a a.log
file and another folder b. The file structure like this:
|- source
|- a.log
|- b
|- target
Now we want to recursively copy all files under source to target:
use std::process::Command;
fn main() {
// cp -r source target
let status = Command::new("cp")
.arg("-r")
.arg("source")
.arg("target")
.status()
.unwrap();
println!("cp status: {}", status);
}
If we run this, we could see it copied the source folder under target, like this:
|- source
|- a.log
|- b
|- target
|- source
|- a.log
|- b
But this is not what I want, I want to only copy file a.log
and folder b
to the target
folder, not the source
folder itself. We know in shell we can simply do cp -r source/* target
, so let's try to change the code to:
let status = Command::new("cp")
.arg("-r")
.arg("source/*")
.arg("target")
.status()
.unwrap();
Now if we run the code, we will actually get an error:
cp: source/*: No such file or directory
cp status: exit code: 1
The program treated source/*
as a single file, which in this case, we don't have a file named as source/*
. It doesn't work.
So what's the solution? Well, we can use sh -c "cp -r source/* target"
!
let status = Command::new("sh")
.arg("-c")
.arg("cp -r source/* target")
.status()
.unwrap();
println!("cp status: {}", status);
Now if we run the code, we can see cp status: exit code: 0
print out, and our file structure like this:
|- source
|- a.log
|- b
|- target
|- a.log
|- b
It works!
P.S, While Rust has fs::copy
function to copy one single file, it doesn't have function to recursively copy a folder to another. Using the method we just introduced can achieve such goal. Another way is using the fs_extra
crate, but if your program only run in Linux/Unix system, I think directly call shell cp
command is simpler.
Top comments (0)