• 目录操作:简单grep

    目录操作:简单grep

    上一节我们实现了通过Command调用subprocess。这一节,我们将通过自己的代码去实现一个简单的grep。当然了,这种基础的工具你是能找到源码的,而我们的实现也并不像真正的grep那样注重效率,本节的主要作用就在于演示标准库API的使用。

    首先,我们需要对当前目录进行递归,遍历,每当查找到文件的时候,我们回调一个函数。

    于是,我们就有了这么个函数:

    1. use std::env::args;
    2. use std::io;
    3. use std::fs::{self, File, DirEntry};
    4. use std::path::Path;
    5. fn visit_dirs(dir: &Path, pattern: &String, cb: &Fn(&DirEntry, &String)) -> io::Result<()> {
    6. if try!(fs::metadata(dir)).is_dir() {
    7. for entry in try!(fs::read_dir(dir)) {
    8. let entry = try!(entry);
    9. if try!(fs::metadata(entry.path())).is_dir() {
    10. try!(visit_dirs(&entry.path(), pattern, cb));
    11. } else {
    12. cb(&entry, pattern);
    13. }
    14. }
    15. }else{
    16. let entry = try!(try!(fs::read_dir(dir)).next().unwrap());
    17. cb(&entry, pattern);
    18. }
    19. Ok(())
    20. }

    我们有了这样的一个函数,有同学可能觉得这代码眼熟。这不是标准库里的例子改了一下么?

    .

    .

    .

    是啊!

    好了,继续,我们需要读取每个查到的文件,同时判断每一行里有没有所查找的内容。
    我们用一个BufferIO去读取各个文件,同时用String的自带方法来判断内容是否存在。

    1. fn call_back(de: &DirEntry, pt: &String) {
    2. let mut f = File::open(de.path()).unwrap();
    3. let mut buf = io::BufReader::new(f);
    4. for line in io::BufRead::lines(buf) {
    5. let line = line.unwrap_or("".to_string());
    6. if line.contains(pt) {
    7. println!("{}", &line);
    8. }
    9. }
    10. }

    最后,我们将整个函数调用起来,如下:

    1. use std::env::args;
    2. use std::io;
    3. use std::fs::{self, File, DirEntry};
    4. use std::path::Path;
    5. fn visit_dirs(dir: &Path, pattern: &String, cb: &Fn(&DirEntry, &String)) -> io::Result<()> {
    6. if try!(fs::metadata(dir)).is_dir() {
    7. for entry in try!(fs::read_dir(dir)) {
    8. let entry = try!(entry);
    9. if try!(fs::metadata(entry.path())).is_dir() {
    10. try!(visit_dirs(&entry.path(), pattern, cb));
    11. } else {
    12. cb(&entry, pattern);
    13. }
    14. }
    15. }else{
    16. let entry = try!(try!(fs::read_dir(dir)).next().unwrap());
    17. cb(&entry, pattern);
    18. }
    19. Ok(())
    20. }
    21. fn call_back(de: &DirEntry, pt: &String) {
    22. let mut f = File::open(de.path()).unwrap();
    23. let mut buf = io::BufReader::new(f);
    24. for line in io::BufRead::lines(buf) {
    25. let line = line.unwrap_or("".to_string());
    26. if line.contains(pt) {
    27. println!("{}", &line);
    28. }
    29. }
    30. }
    31. // 实现调用grep命令搜索文件
    32. fn main() {
    33. let mut arg_iter = args();
    34. arg_iter.next();
    35. // panic if there is no one
    36. let pattern = arg_iter.next().unwrap_or("main".to_string());
    37. let pt = arg_iter.next().unwrap_or("./".to_string());
    38. let pt = Path::new(&pt);
    39. visit_dirs(&pt, &pattern, &call_back).unwrap();
    40. }

    调用如下:

    1. demo git:(master) ./target/debug/demo "fn main()" ../
    2. fn main() {
    3. fn main() { }
    4. fn main() {
    5. pub fn main() {
    6. pub fn main() {}
    7. fn main() {
    8. pub fn main() {
    9. pub fn main() {}