mirror of
https://github.com/sharkdp/fd.git
synced 2024-09-28 13:01:30 +02:00
Implement --batch-size
(#866)
This commit is contained in:
parent
7b5b3ec47b
commit
17dd2a6dfe
@ -12,6 +12,8 @@
|
|||||||
|
|
||||||
- Add new `--no-ignore-parent` flag, see #787 (@will459)
|
- Add new `--no-ignore-parent` flag, see #787 (@will459)
|
||||||
|
|
||||||
|
- Add new `--batch-size` flag, see #410 (@devonhollowood)
|
||||||
|
|
||||||
## Bugfixes
|
## Bugfixes
|
||||||
|
|
||||||
- Set default path separator to `/` in MSYS, see #537 and #730 (@aswild)
|
- Set default path separator to `/` in MSYS, see #537 and #730 (@aswild)
|
||||||
|
@ -138,6 +138,7 @@ _fd() {
|
|||||||
+ '(exec-cmds)' # execute command
|
+ '(exec-cmds)' # execute command
|
||||||
'(long-listing max-results)'{-x+,--exec=}'[execute command for each search result]:command: _command_names -e:*\;::program arguments: _normal'
|
'(long-listing max-results)'{-x+,--exec=}'[execute command for each search result]:command: _command_names -e:*\;::program arguments: _normal'
|
||||||
'(long-listing max-results)'{-X+,--exec-batch=}'[execute command for all search results at once]:command: _command_names -e:*\;::program arguments: _normal'
|
'(long-listing max-results)'{-X+,--exec-batch=}'[execute command for all search results at once]:command: _command_names -e:*\;::program arguments: _normal'
|
||||||
|
'(long-listing max-results)'{--batch-size=}'[max number of args for each -X call]:size'
|
||||||
|
|
||||||
+ other
|
+ other
|
||||||
'!(--max-buffer-time)--max-buffer-time=[set amount of time to buffer before showing output]:time (ms)'
|
'!(--max-buffer-time)--max-buffer-time=[set amount of time to buffer before showing output]:time (ms)'
|
||||||
|
6
doc/fd.1
vendored
6
doc/fd.1
vendored
@ -405,5 +405,11 @@ $ fd -e py
|
|||||||
.TP
|
.TP
|
||||||
.RI "Open all search results with vim:"
|
.RI "Open all search results with vim:"
|
||||||
$ fd pattern -X vim
|
$ fd pattern -X vim
|
||||||
|
.TP
|
||||||
|
.BI "\-\-batch\-size " size
|
||||||
|
Pass at most
|
||||||
|
.I size
|
||||||
|
arguments to each call to the command given with -X.
|
||||||
|
.TP
|
||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
.BR find (1)
|
.BR find (1)
|
||||||
|
15
src/app.rs
15
src/app.rs
@ -365,6 +365,21 @@ pub fn build_app() -> App<'static, 'static> {
|
|||||||
"
|
"
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("batch-size")
|
||||||
|
.long("batch-size")
|
||||||
|
.takes_value(true)
|
||||||
|
.value_name("size")
|
||||||
|
.hidden_short_help(true)
|
||||||
|
.requires("exec-batch")
|
||||||
|
.help("Max number of arguments to run as a batch with -X")
|
||||||
|
.long_help(
|
||||||
|
"Maximum number of arguments to pass to the command given with -X. \
|
||||||
|
If the number of results is greater than the given size, \
|
||||||
|
the command given with -X is run again with remaining arguments. \
|
||||||
|
A batch size of zero means there is no limit.",
|
||||||
|
),
|
||||||
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("exclude")
|
Arg::with_name("exclude")
|
||||||
.long("exclude")
|
.long("exclude")
|
||||||
|
@ -85,6 +85,10 @@ pub struct Config {
|
|||||||
/// If a value is supplied, each item found will be used to generate and execute commands.
|
/// If a value is supplied, each item found will be used to generate and execute commands.
|
||||||
pub command: Option<Arc<CommandTemplate>>,
|
pub command: Option<Arc<CommandTemplate>>,
|
||||||
|
|
||||||
|
/// Maximum number of search results to pass to each `command`. If zero, the number is
|
||||||
|
/// unlimited.
|
||||||
|
pub batch_size: usize,
|
||||||
|
|
||||||
/// A list of glob patterns that should be excluded from the search.
|
/// A list of glob patterns that should be excluded from the search.
|
||||||
pub exclude_patterns: Vec<String>,
|
pub exclude_patterns: Vec<String>,
|
||||||
|
|
||||||
|
@ -50,6 +50,7 @@ pub fn batch(
|
|||||||
cmd: &CommandTemplate,
|
cmd: &CommandTemplate,
|
||||||
show_filesystem_errors: bool,
|
show_filesystem_errors: bool,
|
||||||
buffer_output: bool,
|
buffer_output: bool,
|
||||||
|
limit: usize,
|
||||||
) -> ExitCode {
|
) -> ExitCode {
|
||||||
let paths = rx.iter().filter_map(|value| match value {
|
let paths = rx.iter().filter_map(|value| match value {
|
||||||
WorkerResult::Entry(val) => Some(val),
|
WorkerResult::Entry(val) => Some(val),
|
||||||
@ -60,5 +61,17 @@ pub fn batch(
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
cmd.generate_and_execute_batch(paths, buffer_output)
|
if limit == 0 {
|
||||||
|
// no limit
|
||||||
|
return cmd.generate_and_execute_batch(paths, buffer_output);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut exit_codes = Vec::new();
|
||||||
|
let mut peekable = paths.peekable();
|
||||||
|
while peekable.peek().is_some() {
|
||||||
|
let limited = peekable.by_ref().take(limit);
|
||||||
|
let exit_code = cmd.generate_and_execute_batch(limited, buffer_output);
|
||||||
|
exit_codes.push(exit_code);
|
||||||
|
}
|
||||||
|
merge_exitcodes(exit_codes)
|
||||||
}
|
}
|
||||||
|
@ -348,6 +348,12 @@ fn construct_config(matches: clap::ArgMatches, pattern_regex: &str) -> Result<Co
|
|||||||
})
|
})
|
||||||
.transpose()?,
|
.transpose()?,
|
||||||
command: command.map(Arc::new),
|
command: command.map(Arc::new),
|
||||||
|
batch_size: matches
|
||||||
|
.value_of("batch-size")
|
||||||
|
.map(|n| n.parse::<usize>())
|
||||||
|
.transpose()
|
||||||
|
.context("Failed to parse --batch-size argument")?
|
||||||
|
.unwrap_or_default(),
|
||||||
exclude_patterns: matches
|
exclude_patterns: matches
|
||||||
.values_of("exclude")
|
.values_of("exclude")
|
||||||
.map(|v| v.map(|p| String::from("!") + p).collect())
|
.map(|v| v.map(|p| String::from("!") + p).collect())
|
||||||
|
@ -179,7 +179,13 @@ fn spawn_receiver(
|
|||||||
// This will be set to `Some` if the `--exec` argument was supplied.
|
// This will be set to `Some` if the `--exec` argument was supplied.
|
||||||
if let Some(ref cmd) = config.command {
|
if let Some(ref cmd) = config.command {
|
||||||
if cmd.in_batch_mode() {
|
if cmd.in_batch_mode() {
|
||||||
exec::batch(rx, cmd, show_filesystem_errors, enable_output_buffering)
|
exec::batch(
|
||||||
|
rx,
|
||||||
|
cmd,
|
||||||
|
show_filesystem_errors,
|
||||||
|
enable_output_buffering,
|
||||||
|
config.batch_size,
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
let shared_rx = Arc::new(Mutex::new(rx));
|
let shared_rx = Arc::new(Mutex::new(rx));
|
||||||
|
|
||||||
|
@ -1418,6 +1418,48 @@ fn test_exec_batch() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_exec_batch_with_limit() {
|
||||||
|
// TODO Test for windows
|
||||||
|
if cfg!(windows) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let te = TestEnv::new(DEFAULT_DIRS, DEFAULT_FILES);
|
||||||
|
|
||||||
|
te.assert_output(
|
||||||
|
&["foo", "--batch-size", "0", "--exec-batch", "echo", "{}"],
|
||||||
|
"a.foo one/b.foo one/two/C.Foo2 one/two/c.foo one/two/three/d.foo one/two/three/directory_foo",
|
||||||
|
);
|
||||||
|
|
||||||
|
let output = te.assert_success_and_get_output(
|
||||||
|
".",
|
||||||
|
&["foo", "--batch-size=2", "--exec-batch", "echo", "{}"],
|
||||||
|
);
|
||||||
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||||
|
|
||||||
|
for line in stdout.lines() {
|
||||||
|
assert_eq!(2, line.split_whitespace().count());
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut paths: Vec<_> = stdout
|
||||||
|
.lines()
|
||||||
|
.flat_map(|line| line.split_whitespace())
|
||||||
|
.collect();
|
||||||
|
paths.sort_unstable();
|
||||||
|
assert_eq!(
|
||||||
|
&paths,
|
||||||
|
&[
|
||||||
|
"a.foo",
|
||||||
|
"one/b.foo",
|
||||||
|
"one/two/C.Foo2",
|
||||||
|
"one/two/c.foo",
|
||||||
|
"one/two/three/d.foo",
|
||||||
|
"one/two/three/directory_foo"
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/// Shell script execution (--exec) with a custom --path-separator
|
/// Shell script execution (--exec) with a custom --path-separator
|
||||||
#[test]
|
#[test]
|
||||||
fn test_exec_with_separator() {
|
fn test_exec_with_separator() {
|
||||||
|
Loading…
Reference in New Issue
Block a user