Rewrite of file-type filtering leading to 5% speed-up

This commit is contained in:
sharkdp 2018-02-25 11:11:14 +01:00 committed by David Peter
parent e5ee5eb7b3
commit 40d811c7be
3 changed files with 44 additions and 38 deletions

View File

@ -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.
///

View File

@ -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)));

View File

@ -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.