mirror of https://github.com/sharkdp/fd.git
Rewrite of file-type filtering leading to 5% speed-up
This commit is contained in:
parent
e5ee5eb7b3
commit
40d811c7be
|
@ -6,7 +6,6 @@
|
|||
// notice may not be copied, modified, or distributed except
|
||||
// according to those terms.
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::ffi::OsString;
|
||||
use std::process;
|
||||
use std::time;
|
||||
|
@ -14,10 +13,26 @@ use std::io::Write;
|
|||
|
||||
use exec::CommandTemplate;
|
||||
use lscolors::LsColors;
|
||||
use walk::FileType;
|
||||
use regex_syntax::{Expr, ExprBuilder};
|
||||
use regex::RegexSet;
|
||||
|
||||
/// Whether or not to show
|
||||
pub struct FileTypes {
|
||||
pub files: bool,
|
||||
pub directories: bool,
|
||||
pub symlinks: bool,
|
||||
}
|
||||
|
||||
impl Default for FileTypes {
|
||||
fn default() -> FileTypes {
|
||||
FileTypes {
|
||||
files: false,
|
||||
directories: false,
|
||||
symlinks: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Configuration options for *fd*.
|
||||
pub struct FdOptions {
|
||||
/// Whether the search is case-sensitive or case-insensitive.
|
||||
|
@ -60,8 +75,9 @@ pub struct FdOptions {
|
|||
/// how to style different filetypes.
|
||||
pub ls_colors: Option<LsColors>,
|
||||
|
||||
/// The type of file to search for. All files other than the specified type will be ignored.
|
||||
pub file_types: HashSet<FileType>,
|
||||
/// The type of file to search for. If set to `None`, all file types are displayed. If
|
||||
/// set to `Some(..)`, only the types that are specified are shown.
|
||||
pub file_types: Option<FileTypes>,
|
||||
|
||||
/// The extension to search for. Only entries matching the extension will be included.
|
||||
///
|
||||
|
|
31
src/main.rs
31
src/main.rs
|
@ -40,9 +40,8 @@ use atty::Stream;
|
|||
use regex::{RegexBuilder, RegexSetBuilder};
|
||||
|
||||
use exec::CommandTemplate;
|
||||
use internal::{error, pattern_has_uppercase_char, transform_args_with_exec, FdOptions};
|
||||
use internal::{error, pattern_has_uppercase_char, transform_args_with_exec, FdOptions, FileTypes};
|
||||
use lscolors::LsColors;
|
||||
use walk::FileType;
|
||||
|
||||
fn main() {
|
||||
let checked_args = transform_args_with_exec(env::args_os());
|
||||
|
@ -142,22 +141,18 @@ fn main() {
|
|||
.and_then(|n| u64::from_str_radix(n, 10).ok())
|
||||
.map(time::Duration::from_millis),
|
||||
ls_colors,
|
||||
file_types: match matches.values_of("file-type") {
|
||||
None => vec![
|
||||
FileType::RegularFile,
|
||||
FileType::Directory,
|
||||
FileType::SymLink,
|
||||
].into_iter()
|
||||
.collect(),
|
||||
Some(values) => values
|
||||
.map(|value| match value {
|
||||
"f" | "file" => FileType::RegularFile,
|
||||
"d" | "directory" => FileType::Directory,
|
||||
"l" | "symlink" => FileType::SymLink,
|
||||
_ => FileType::RegularFile,
|
||||
})
|
||||
.collect(),
|
||||
},
|
||||
file_types: matches.values_of("file-type").map(|values| {
|
||||
let mut file_types = FileTypes::default();
|
||||
for value in values {
|
||||
match value {
|
||||
"f" | "file" => file_types.files = true,
|
||||
"d" | "directory" => file_types.directories = true,
|
||||
"l" | "symlink" => file_types.symlinks = true,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
file_types
|
||||
}),
|
||||
extensions: matches.values_of("extension").map(|exts| {
|
||||
let patterns = exts.map(|e| e.trim_left_matches('.'))
|
||||
.map(|e| format!(r".\.{}$", regex::escape(e)));
|
||||
|
|
27
src/walk.rs
27
src/walk.rs
|
@ -35,14 +35,6 @@ enum ReceiverMode {
|
|||
Streaming,
|
||||
}
|
||||
|
||||
/// The types of file to search for.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum FileType {
|
||||
RegularFile,
|
||||
Directory,
|
||||
SymLink,
|
||||
}
|
||||
|
||||
/// Recursively scan the given search path for files / pathnames matching the pattern.
|
||||
///
|
||||
/// If the `--exec` argument was supplied, this will create a thread pool for executing
|
||||
|
@ -206,14 +198,17 @@ pub fn scan(path_vec: &[PathBuf], pattern: Arc<Regex>, config: Arc<FdOptions>) {
|
|||
}
|
||||
|
||||
// Filter out unwanted file types.
|
||||
if (entry.file_type().map_or(false, |ft| ft.is_file())
|
||||
&& !config.file_types.contains(&FileType::RegularFile))
|
||||
|| (entry.file_type().map_or(false, |ft| ft.is_dir())
|
||||
&& !config.file_types.contains(&FileType::Directory))
|
||||
|| (entry.file_type().map_or(false, |ft| ft.is_symlink())
|
||||
&& !config.file_types.contains(&FileType::SymLink))
|
||||
{
|
||||
return ignore::WalkState::Continue;
|
||||
if let Some(ref file_types) = config.file_types {
|
||||
if let Some(ref entry_type) = entry.file_type() {
|
||||
if (entry_type.is_file() && !file_types.files)
|
||||
|| (entry_type.is_dir() && !file_types.directories)
|
||||
|| (entry_type.is_symlink() && !file_types.symlinks)
|
||||
{
|
||||
return ignore::WalkState::Continue;
|
||||
}
|
||||
} else {
|
||||
return ignore::WalkState::Continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Filter out unwanted extensions.
|
||||
|
|
Loading…
Reference in New Issue