-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.
Replaces assert_cmd/predicates/pretty_assertions/serial_test with uutests and
ctor in dev-dependencies.
Closes https://github.com/uutils/findutils/issues/537.
- Port tests/find_cmd_tests.rs → tests/test_find.rs (uutests API)
- Port tests/xargs_tests.rs → tests/test_xargs.rs (uutests API)
- Centralize UUTESTS_BINARY_PATH init via #[ctor::ctor] in tests/common/mod.rs
Implementation notes:
- Use TestScenario::cmd(BINARY_PATH) rather than ucmd(): find/xargs are
dedicated binaries, not multi-call, so ucmd() would prepend the utility name
as a spurious first argument
- Set CWD to CARGO_MANIFEST_DIR in find's ucmd() so relative test_data/ paths
resolve correctly regardless of where cargo runs
- delete_on_dot_dir sets the child process CWD via UCommand::current_dir()
instead of mutating the process-wide CWD, removing the need for serial_test
and all #[serial(working_dir)] attributes
Also fixes find_samefile, find_fprinter, and find_fprintf, which were writing
temporary files directly into test_data/. They now use isolated temp
directories, eliminating a source of test pollution when running in parallel.
* Add -follow support.
* tests/find: Serialize find_time()
find_time() relies on the working directory, but e.g.
delete_on_dot_dir() will temporarily change directories, causing
find_time() to fail when run in parallel.
* find: Don't use uutils::error::set_exit_code()
The global exit code can polute the results of other tests.
Link: https://github.com/uutils/coreutils/issues/5777
* find: New WalkEntry wrapper
The new type wraps DirEntry when possible, but also lets us pass a valid
entry to matchers when walkdir returns a broken symlink error. It also
implements a Metadata cache (part of #430).
* find: Implement -H, -L, -P flags
* find: Fix -follow -samefile
* find: Fix -follow -newer
* find: Implement -xtype
* find: Fix -delete error handling
---------
Co-authored-by: hanbings <hanbings@hanbings.io>
* Deleted vertical whitespace
In an attempt to get around a mistake I made when merging from the
master fork
* Added a default implementation for has_side_effects
And removed all the "return false" implementations (as specified by most
of the Matchers).
* Added support for -exec and -execdir
* Fixed path_to_testing_commandline
* Minor tweaks from code review
* Added support for -perm
* Fixed string constant
* Fixed error caused by merging changes
* Tweaks after code review
* Fixed windows compatability. This required
- changing a lot of test code to supply/expect backslashes rather than
slashes when running on windows
- tweaking the way testing-commandline reported its args (debug format
escapes backslashes when printing strings)
- changing the NewerMatcher to get metadata from fs::metadata() rather
than from File's metadata method (the latter caused mysterious test
failures, which I didn't bother tracking down becasue the former is more
efficient anyway)
- hiding more of perm.rs behind #[cfg(unix)] to stop "unused X"
warnings
* Revert "Fixed windows compatability. This required"
This reverts commit 0e2c385237.
* Revert "Revert "Fixed windows compatability. This required""
This reverts commit 384da6d2f4.
* Deleted vertical whitespace
In an attempt to get around a mistake I made when merging from the
master fork
* Added a default implementation for has_side_effects
And removed all the "return false" implementations (as specified by most
of the Matchers).
* Added support for -exec and -execdir
* Fixed path_to_testing_commandline
* Minor tweaks from code review