Add --min-depth and --exact-depth

Add new `--min-depth <depth>` and `--exact-depth <depth>` options in addition to the existing
option to limit the maximum depth.

closes #404
This commit is contained in:
sharkdp 2020-04-15 16:17:01 +02:00 committed by David Peter
parent 47974b6479
commit d63c63be8c
7 changed files with 89 additions and 2 deletions

View File

@ -12,6 +12,8 @@
This can be useful to speed up searches in cases where you know that there are only N results.
Using this option is also (slightly) faster than piping to `head -n <count>` where `fd` can only
exit when it finds the search results `<count> + 1`.
- Add new `--min-depth <depth>` and `--exact-depth <depth>` options in addition to the existing option
to limit the maximum depth. See #404.
- Add the alias `-1` for `--max-results=1`, see #561. (@SimplyDanny).
- Support additional ANSI font styles in `LS_COLORS`: faint, slow blink, rapid blink, dimmed, hidden and strikethrough.

6
doc/fd.1 vendored
View File

@ -110,6 +110,12 @@ Limit directory traversal to at most
.I d
levels of depth. By default, there is no limit on the search depth.
.TP
.BI "\-\-min\-depth " d
Only show search results starting at the given depth. See also: '--max-depth' and '--exact-depth'.
.TP
.BI "\-\-exact\-depth " d
Only show search results at the exact given depth. This is an alias for '--min-depth <depth> --max-depth <depth>'.
.TP
.BI "\-t, \-\-type " filetype
Filter search by type:
.RS

View File

@ -168,10 +168,11 @@ pub fn build_app() -> App<'static, 'static> {
),
)
.arg(
Arg::with_name("depth")
Arg::with_name("max-depth")
.long("max-depth")
.short("d")
.takes_value(true)
.value_name("depth")
.help("Set maximum search depth (default: none)")
.long_help(
"Limit the directory traversal to a given depth. By default, there is no \
@ -185,6 +186,29 @@ pub fn build_app() -> App<'static, 'static> {
.hidden(true)
.takes_value(true)
)
.arg(
Arg::with_name("min-depth")
.long("min-depth")
.takes_value(true)
.value_name("depth")
.hidden_short_help(true)
.long_help(
"Only show search results starting at the given depth. \
See also: '--max-depth' and '--exact-depth'",
),
)
.arg(
Arg::with_name("exact-depth")
.long("exact-depth")
.takes_value(true)
.value_name("depth")
.hidden_short_help(true)
.conflicts_with_all(&["max-depth", "min-depth"])
.long_help(
"Only show search results at the exact given depth. This is an alias for \
'--min-depth <depth> --max-depth <depth>'.",
),
)
.arg(
Arg::with_name("file-type")
.long("type")

View File

@ -226,8 +226,13 @@ fn run() -> Result<ExitCode> {
one_file_system: matches.is_present("one-file-system"),
null_separator: matches.is_present("null_separator"),
max_depth: matches
.value_of("depth")
.value_of("max-depth")
.or_else(|| matches.value_of("rg-depth"))
.or_else(|| matches.value_of("exact-depth"))
.and_then(|n| usize::from_str_radix(n, 10).ok()),
min_depth: matches
.value_of("min-depth")
.or_else(|| matches.value_of("exact-depth"))
.and_then(|n| usize::from_str_radix(n, 10).ok()),
threads: std::cmp::max(
matches

View File

@ -40,6 +40,9 @@ pub struct Options {
/// all files under subdirectories of the current directory, etc.
pub max_depth: Option<usize>,
/// The minimum depth for reported entries, or `None`.
pub min_depth: Option<usize>,
/// The number of threads to use.
pub threads: usize,

View File

@ -283,6 +283,13 @@ impl DirEntry {
DirEntry::BrokenSymlink(_) => None,
}
}
pub fn depth(&self) -> Option<usize> {
match self {
DirEntry::Normal(e) => Some(e.depth()),
DirEntry::BrokenSymlink(_) => None,
}
}
}
fn spawn_senders(
@ -338,6 +345,12 @@ fn spawn_senders(
}
};
if let Some(min_depth) = config.min_depth {
if entry.depth().map_or(true, |d| d < min_depth) {
return ignore::WalkState::Continue;
}
}
// Check the name first, since it doesn't require metadata
let entry_path = entry.path();

View File

@ -679,6 +679,40 @@ fn test_max_depth() {
);
}
/// Minimum depth (--min-depth)
#[test]
fn test_min_depth() {
let te = TestEnv::new(DEFAULT_DIRS, DEFAULT_FILES);
te.assert_output(
&["--min-depth", "3"],
"one/two/c.foo
one/two/C.Foo2
one/two/three
one/two/three/d.foo
one/two/three/directory_foo",
);
te.assert_output(
&["--min-depth", "4"],
"one/two/three/d.foo
one/two/three/directory_foo",
);
}
/// Exact depth (--exact-depth)
#[test]
fn test_exact_depth() {
let te = TestEnv::new(DEFAULT_DIRS, DEFAULT_FILES);
te.assert_output(
&["--exact-depth", "3"],
"one/two/c.foo
one/two/C.Foo2
one/two/three",
);
}
/// Absolute paths (--absolute-path)
#[test]
fn test_absolute_path() {