【Rust】6、练习:自己实现 ls
文章目录
- 一、CLI Utilities
Rust 学完,想找些练手的项目,怎么办?可参考这个文章,列出的 15 个项目。
一、CLI Utilities
github
参考
lsd 项目地址
cargo.toml
[dependencies]
clap = "2"
main.rs
extern crate clap;
use clap::{App, Arg};
fn main() {
let app = App::new("l")
.version("1.0.0")
.author("y")
.about("this is a l")
.arg(
Arg::with_name("all")
.short("a")
.help("show all file and dir"),
)
.arg(Arg::with_name("long").short("l").help("show file all info"))
.arg(Arg::with_name("FILE").multiple(true).default_value("."))
.get_matches();
let all = app.is_present("all");
let long = app.is_present("long");
let files: Vec<&str> = app.values_of("FILE").expect("not get any file").collect();
println!("all: {}, long: {}, File: {:?}", all, long, files);
}
运行已经可以收到命令行参数了,如下:
# cargo run
all: false, long: false, File: ["."]
# cargo run -- -a -l /tmp /etc
all: true, long: true, File: ["/tmp", "/etc"]
接下来读取某路径下的文件:
extern crate clap;
use std::{fs::read_dir, path::Path};
fn main() {
let files = vec!["/Users"];
for file in files {
let path = Path::new(file);
if path.is_dir() {
println!("{} is a directory", file);
let somes = read_dir(path).expect("not get this path");
for some in somes {
if let Ok(ref entry) = some {
let name = entry
.file_name()
.to_str()
.expect("file name convert str fail")
.to_string();
let data = entry.metadata().expect("no metadata");
println!("{} {:?}", name, data)
}
}
}
}
}
接下来把两个程序结合:
extern crate clap;
use clap::{App, Arg};
use std::fs::read_dir;
use std::os::unix::fs::PermissionsExt;
use std::path::Path;
#[derive(Debug)]
pub struct Option {
display_all: bool,
display_long: bool,
}
fn main() {
let app = App::new("l")
.version("1.0.0")
.author("lome")
.about("this is a l")
.arg(
Arg::with_name("all")
.short("a")
.help("Show all file and dir"),
)
.arg(Arg::with_name("long").short("l").help("show file all info"))
.arg(Arg::with_name("FILE").multiple(true).default_value("."))
.get_matches();
let option = Option {
display_all: app.is_present("all"),
display_long: app.is_present("long"),
};
let files: Vec<&str> = app.values_of("FILE").expect("not get any file").collect();
for file in files {
let path = Path::new(file);
if path.is_dir() {
println!("{}: ", file);
let somes = read_dir(path).expect("not get this path");
for some in somes {
if let Ok(ref entry) = some {
let name = entry
.file_name()
.to_str()
.expect("file name convert str fail")
.to_string();
let data = entry.metadata().expect("no metadata");
if option.display_long {
if option.display_all || !name.starts_with(".") {
let permission = data.permissions().mode();
let systime = data.modified().expect("get system time error");
println!(
" {} Permission: {:o} Systime: {:?}",
name, permission, systime
);
}
} else {
if option.display_all || !name.starts_with(".") {
println!(" {}", name);
}
}
}
}
}
}
}
// code result:
Output:
$ ./l ./test/ ./test/test/
./test/:
test.txt
test
./test/test/:
test.txt
$ ./l -a ./test/ ./test/test/
./test/:
test.txt
test
.test.txt
./test/test/:
test.txt
$ ./l -al ./test/ ./test/test/
./test/:
test.txt Permission: 100644 Systime: SystemTime { tv_sec: 1573805933, tv_nsec: 470337261 }
test Permission: 40755 Systime: SystemTime { tv_sec: 1573805940, tv_nsec: 228706396 }
.test.txt Permission: 100644 Systime: SystemTime { tv_sec: 1573806564, tv_nsec: 333715123 }
./test/test/:
test.txt Permission: 100644 Systime: SystemTime { tv_sec: 1573805940, tv_nsec: 228706396 }