Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 21 additions & 21 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions datetime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ libc.workspace = true

[[bin]]
name = "cal"
path = "src/cal.rs"
path = "./cal.rs"

[[bin]]
name = "date"
path = "src/date.rs"
path = "./date.rs"

[[bin]]
name = "sleep"
path = "src/sleep.rs"
path = "./sleep.rs"

File renamed without changes.
File renamed without changes.
File renamed without changes.
91 changes: 53 additions & 38 deletions file/src/find.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@
// SPDX-License-Identifier: MIT
//

use std::collections::HashSet;
use std::{env, fs};
use std::os::unix::fs::{FileTypeExt, MetadataExt, PermissionsExt};
use std::path::PathBuf;
use gettextrs::{bind_textdomain_codeset, textdomain};
use plib::PROJECT_NAME;
use regex::Regex;
use std::collections::HashSet;
use std::os::unix::fs::{FileTypeExt, MetadataExt, PermissionsExt};
use std::path::PathBuf;
use std::{env, fs};
use walkdir::{DirEntry, WalkDir};

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -51,7 +51,7 @@ enum FileType {
}

/// Parses a list of tokens representing search criteria, the result is stored in enum Expr
///
///
/// # Arguments
///
/// * `tokens` - A vector of string slices representing the tokens to parse.
Expand Down Expand Up @@ -184,7 +184,9 @@ fn parse_expression(tokens: &mut Vec<&str>) -> Vec<Expr> {
}
_ => {
tokens.pop();
stack.push(Expr::Path(PathBuf::from(token).to_string_lossy().to_string()));
stack.push(Expr::Path(
PathBuf::from(token).to_string_lossy().to_string(),
));
}
}
}
Expand All @@ -206,10 +208,12 @@ fn pattern_to_regex(pattern: &str) -> Regex {
regex_pattern = regex_pattern.replace('*', ".*");

let bracket_regex = Regex::new(r"\[(?:[^\]]+)\]").unwrap();
regex_pattern = bracket_regex.replace_all(&regex_pattern, |caps: &regex::Captures| {
let bracket_content = &caps[0][1..caps[0].len()-1];
format!("[{}]", bracket_content)
}).to_string();
regex_pattern = bracket_regex
.replace_all(&regex_pattern, |caps: &regex::Captures| {
let bracket_content = &caps[0][1..caps[0].len() - 1];
format!("[{}]", bracket_content)
})
.to_string();

Regex::new(&format!("^{}$", regex_pattern)).unwrap()
}
Expand All @@ -226,58 +230,68 @@ fn pattern_to_regex(pattern: &str) -> Regex {
///
/// * A `Result` containing a vector of `PathBuf` objects representing the paths of the files that match the expressions,
/// or an error message as a `String`.
fn evaluate_expression(expr: &[Expr], files: Vec<DirEntry>, root_dev: u64) -> Result<Vec<PathBuf>, String> {
fn evaluate_expression(
expr: &[Expr],
files: Vec<DirEntry>,
root_dev: u64,
) -> Result<Vec<PathBuf>, String> {
let f_path = &expr[0];
let mut not_res: Vec<PathBuf> = Vec::new();
let mut or_res: Vec<PathBuf> = Vec::new();
let mut and_res: Vec<PathBuf> = Vec::new();
let mut c_files = files.clone().into_iter().map(|f| f.path().to_path_buf()).collect::<HashSet<PathBuf>>();
let mut c_files = files
.clone()
.into_iter()
.map(|f| f.path().to_path_buf())
.collect::<HashSet<PathBuf>>();
let mut result = Vec::new();
let mut first = true;
for expression in expr {
match expression {
Expr::Not(inner) => {
let i: Vec<Expr> = vec![f_path.clone(), *inner.clone()];
not_res = evaluate_expression(&i.as_slice(), files.clone(), root_dev)?;
},
}
Expr::Or(inner) => {
let i: Vec<Expr> = vec![f_path.clone(), *inner.clone()];
or_res = evaluate_expression(&i.as_slice(), files.clone(), root_dev)?;
},
}
Expr::And(inner) => {
let i: Vec<Expr> = vec![f_path.clone(), *inner.clone()];
and_res = evaluate_expression(&i.as_slice(), files.clone(), root_dev)?;
},
}
_ => {}
}
for file in &files {
match expression {
Expr::And(_) => {
continue;
},
}
Expr::Or(_) => {
continue;
},
}
Expr::Not(_) => {
continue;
},
}
Expr::Name(name) => {
let regex = pattern_to_regex(name);
if !regex.is_match(&file.file_name().to_string_lossy()) {
c_files.remove(file.path());
}
},
}
Expr::Path(path) => {
let regex = pattern_to_regex(path);

if !regex.is_match(&file.path().to_string_lossy()) && !first {
c_files.remove(file.path());
}
},
}
Expr::MTime(days) => {
if let Ok(metadata) = file.metadata() {
let modified = metadata.modified().unwrap();
let duration = std::time::SystemTime::now().duration_since(modified).unwrap();
let duration = std::time::SystemTime::now()
.duration_since(modified)
.unwrap();
if ((duration.as_secs() / 86400) as i64) < (*days) {
c_files.remove(file.path());
}
Expand Down Expand Up @@ -322,9 +336,7 @@ fn evaluate_expression(expr: &[Expr], files: Vec<DirEntry>, root_dev: u64) -> Re
}
}
}
Expr::Prune => {

},
Expr::Prune => {}
Expr::Perm(perm) => {
if let Ok(metadata) = file.metadata() {
if metadata.permissions().mode() & 0o777 != *perm {
Expand Down Expand Up @@ -356,8 +368,7 @@ fn evaluate_expression(expr: &[Expr], files: Vec<DirEntry>, root_dev: u64) -> Re
if gid != parsed_gid {
c_files.remove(file.path());
}
}
else {
} else {
c_files.remove(file.path());
}
}
Expand Down Expand Up @@ -425,15 +436,16 @@ fn evaluate_expression(expr: &[Expr], files: Vec<DirEntry>, root_dev: u64) -> Re
fn get_root(expr: &[Expr]) -> String {
let mut first = true;

let path = expr.iter()
.find_map(|i| match i {
Expr::Path(p) if first => {
first = false;
Some(p.to_string())
},
_ => None,
})
.unwrap_or_else(String::new);
let path = expr
.iter()
.find_map(|i| match i {
Expr::Path(p) if first => {
first = false;
Some(p.to_string())
}
_ => None,
})
.unwrap_or_else(String::new);

path
}
Expand All @@ -459,7 +471,10 @@ fn find(args: Vec<String>) -> Result<(), String> {
return Err("Error: Could not retrieve root device metadata".to_string());
};

let files = WalkDir::new(path).into_iter().map(|f|f.unwrap()).collect::<Vec<DirEntry>>();
let files = WalkDir::new(path)
.into_iter()
.map(|f| f.unwrap())
.collect::<Vec<DirEntry>>();
let result = evaluate_expression(expr, files, root_dev);

for res in result? {
Expand All @@ -471,9 +486,9 @@ fn find(args: Vec<String>) -> Result<(), String> {
fn main() -> Result<(), Box<dyn std::error::Error>> {
textdomain(PROJECT_NAME)?;
bind_textdomain_codeset(PROJECT_NAME, "UTF-8")?;

let args: Vec<String> = env::args().collect();

let mut exit_code = 0;

if let Err(err) = find(args) {
Expand Down
2 changes: 1 addition & 1 deletion file/tests/file-tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@
mod cmp;
mod dd;
mod file;
mod od;
mod find;
mod od;
Loading