cli_util 0.2.35

Command-line utilitiy for unix based systems
Documentation
//! Search a folder hierarchy for filename(s) that meet a desired criteria.
//!
//!
//! Syntax
//!
//!
//!     find <path> -name "pattern"
//! 
//! -name pattern
//!
//!        True if the last component of the pathname being examined matches
//!        pattern.  Special shell pattern matching characters ('[',
//!        ']', '*', and '?') can be used as part of pattern.  These
//!        characters can be matched explicitly by escaping them with a
//!        backslash ('\').
//!
use crate::parse_command_line_args;
use std::fs;
use std::io::Write;
use std::path::Path;


/// manin method of find mechanism
pub fn find(_args: &str, handle: &mut Box<dyn Write>) -> Result<(), Box<dyn std::error::Error>> {
    let mut path = String::new();
    let mut wanted = String::new();
    let mut wanted_arg = false;
    let args = parse_command_line_args(_args);
    for arg in args {
        if arg.chars().next() == Some('-') {
            let arg_name = &arg[1..arg.len()];
            match arg_name {
                "name" => {
                    wanted_arg = true;
                }
                _ => continue,
            }
        } else if wanted_arg {
            wanted = arg;
            wanted_arg = false;
        } else if path.is_empty() {
            path = arg.to_string();
        }
    }

    let wanted = if wanted.starts_with("*") {
        format!(
            "{}$",
            wanted
                .replace("*", ".*")
                .replace(".", "\\.")
                .replace("?", ".")
        )
    } else {
        format!("^{}", wanted.replace("*", ".*").replace("?", "."))
    };
    let path = Path::new(&path);
    find_directory(&path, &wanted, handle)?;
    Ok(())
}
use regex::Regex;

/// subroutine of find mechanism
fn find_directory(
    directory: &Path,
    wanted: &String,
    handle: &mut Box<dyn Write>,
) -> Result<(), Box<dyn std::error::Error>> {
    let paths = fs::read_dir(directory);
    let re = Regex::new(&wanted)?;
    match paths {
        Ok(paths) => {
            for entry in paths {
                let entry = entry?;
                let filename_os_str = entry.file_name();
                let filename = filename_os_str
                    .to_str()
                    .ok_or("Invalid UTF-8 in file name")?;
                let path = entry.path();
                if path.is_dir() {
                    find_directory(&path, &wanted, handle)?;
                }
                if re.is_match(filename) {
                    writeln!(handle, "{}/{}", directory.display(), filename)?;
                }
            }
        }
        Err(error) => {
            if error.kind() == std::io::ErrorKind::PermissionDenied {
                return Ok(());
            }
            eprintln!("{:?} {}", directory, error);
            return Ok(());
        }
    };
    Ok(())
}