-ok is like -exec ... ; but prompts the user on stderr before each
invocation and only runs the command if the response is affirmative
(starts with 'y' or 'Y'). -okdir is the corresponding -execdir variant.
Only the ';' terminator is accepted: POSIX does not define -ok ... + and
GNU find rejects it.
Response source: GNU find reads from /dev/tty so that the user's answer
always comes from the real terminal even when stdin is occupied (e.g.
`find -files0-from - -ok rm {} \;` reads paths from stdin, so responses
cannot also come from there). /dev/tty is the POSIX name for a
process's controlling terminal and exists on all Unix-like systems. We
open /dev/tty only when stdin is itself a terminal
(std::io::stdin().is_terminal() == true). When stdin is a pipe or file,
we read from stdin directly — matching BSD find and making scripted use
(and integration tests via pipe_in()) work naturally without any special
environment variable. On Windows, or when /dev/tty cannot be opened, we
likewise fall back to stdin.
Implementation: rather than a separate OkMatcher that duplicated
SingleExecMatcher's fields, constructor, and exec logic, the interactive
prompt is folded into SingleExecMatcher behind an `interactive: bool`
field. `SingleExecMatcher::new_interactive()` constructs the -ok/-okdir
variant; `matches()` adds a guarded block that builds a GNU-find-style
prompt ("< executable arg... >? ") and calls `matcher_io.confirm()`
before executing. If the user declines, the expression is false and the
command is not run. This keeps the arg-parsing, path resolution,
current_dir logic, and error handling in one place so bug fixes apply to
both -exec and -ok.
Dependencies::confirm() trait method: abstracts prompt+read so matchers
remain testable without a real terminal; FakeDependencies uses a
VecDeque of preset responses.
Tests:
- Unit tests (exec_unit_tests.rs): confirmed executes command, declined
skips command and returns false, confirmed but command fails returns
false, -okdir runs in parent dir
- Parser unit tests (matchers/mod.rs): missing-arg errors, missing
semicolon, correct parse, confirm/decline via FakeDependencies
- Integration tests (test_find.rs): pipe_in() makes stdin a pipe so
is_terminal() returns false and responses are read from the pipe;
"y"/"Y"/"yes"/" y" run command, "n" and empty response skip command,
-okdir runs in parent dir, prompt format verified, missing-semicolon
error
Closes https://github.com/uutils/findutils/issues/8.
GNU xargs treats the arguments to -I, -E, and -e as values even when
they begin with a hyphen. Clap was parsing those strings as options
instead, so invocations like 'xargs -I -_' failed before xargs could
process input.
Allow hyphen-leading values for those options and add regression
coverage for replacement and EOF markers that start with '-'.
If you stack two mounts on top of each other, e.g.
# mount -t ext4 /dev/sdX /mnt
# mount -t f2fs /dev/sdY /mnt
then read_fs_list() will return two entries for that mount point. The
later one is the one with the correct type, since the later mount is on
top of the earlier one.
POSIX says
> -user uname
> The primary shall evaluate as true if the file belongs to the user
> uname. If uname is a decimal integer and the getpwnam() (or
> equivalent) function does not return a valid user name, uname shall
> be interpreted as a user ID.
and similarly for -group.
Link: https://pubs.opengroup.org/onlinepubs/9799919799/utilities/find.html
These tests failed on my system because directory entries were returned
in a different order, causing an output mismatch. Add --sort to the
testing_commandline to make the output deterministic.
* add argmax dependency
* implement finished and finished_dir callback
* implement multi exec matcher
* fix finished_dir not working correctly
* add more test for multi exec matcher
* fix execdir multi in current directory not working
* add more test for parsing multi exec
* set exit code when exec + failed
* fix clippy warnings
* prevent multi exec panics on long paths
---------
Co-authored-by: hanbings <hanbings@hanbings.io>