From aa6797db463b5143c5ca05bb5e90b05d2f72122a Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Tue, 19 Apr 2022 11:30:47 -0400 Subject: docs: Move some documentation into a subfolder --- docs/CHANGELOG.md | 655 +++++++++++++++++++++++++++++++++++++++++ docs/CONTRIBUTING.md | 167 +++++++++++ docs/bfs.1 | 811 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 1633 insertions(+) create mode 100644 docs/CHANGELOG.md create mode 100644 docs/CONTRIBUTING.md create mode 100644 docs/bfs.1 (limited to 'docs') diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md new file mode 100644 index 0000000..aafc497 --- /dev/null +++ b/docs/CHANGELOG.md @@ -0,0 +1,655 @@ +2.* +=== + +2.5 +--- + +**March 27, 2022** + +- Added compiler-style context for errors and warnings. + Errors look like this: + + $ bfs -nam needle + bfs: error: bfs -nam needle + bfs: error: ~~~~ + bfs: error: Unknown argument; did you mean -name? + + and warnings look like this: + + $ bfs -print -name 'needle' + bfs: warning: bfs -print -name needle + bfs: warning: ~~~~~~~~~~~~ + bfs: warning: The result of this expression is ignored. + +- Updated from C99 to C11 + +- Fixed the tests when built against musl + +- Fixed a build error reported on Manjaro + + +2.4.1 +----- + +**February 24, 2022** + +- Fixed the build when Oniguruma is not installed in the default search paths ([#82]) + +- Fixed string encoding bugs with Oniguruma enabled + +- Fixed regex error reporting bugs + +[#82]: https://github.com/tavianator/bfs/issues/82 + + +2.4 +--- + +**February 22, 2022** + +- Added the Oniguruma regular expression library as an (optional, but enabled by default) dependency ([#81]). + Oniguruma supports more regular expression syntax types than the POSIX regex API, and often performs better. + To build `bfs` without this new dependency, do `make WITH_ONIGURUMA=` to disable it. + Thanks @data-man! + +- Added support for the `ed`, `emacs`, `grep`, and `sed` regular expression types ([#21]) + +- Before executing a process with `-exec[dir]`/`-ok[dir]`, `bfs` now ensures all output streams are flushed. + Previously, I/O from subprocesses could be interleaved unpredictably with buffered I/O from `bfs` itself. + +[#81]: https://github.com/tavianator/bfs/pull/81 +[#21]: https://github.com/tavianator/bfs/issues/21 + + +2.3.1 +----- + +**January 21, 2022** + +- Fixed the build on Debian kFreeBSD + +- Fixed a crash on GNU Hurd when piping bfs's output + +- Fixed a double-`close()` on non-Linux platforms if `fdopendir()` fails + +- Reduced memory allocations on startup + + +2.3 +--- + +**November 25, 2021** + +- More tweaks to `PAGER` and `LESS` handling for `bfs -help` ([#76]) + +- Use 512-byte blocks for `-ls` when `POSIXLY_CORRECT` is set ([#77]) + +- Implemented `-files0-from FILE` to take a list of `'\0'`-separated starting paths. + GNU find will implement the same feature in an upcoming release. + +- Added colors to `-printf` output ([#62]) + +- Faster recovery from `E2BIG` during `-exec` + +[#76]: https://github.com/tavianator/bfs/issues/76 +[#77]: https://github.com/tavianator/bfs/issues/77 +[#62]: https://github.com/tavianator/bfs/issues/62 + + +2.2.1 +----- + +**June 2, 2021** + +- Fixed some incorrect coloring of broken links when links are being followed (`-L`) + +- Made the tests work when run as root by dropping privileges. + This may be helpful for certain packaging or CI environments, but is not recommended. + +- Treat empty `PAGER` and `LESS` environment variables like they're unset, for `bfs -help` ([#71]). + Thanks @markus-oberhumer! + +- The soft `RLIMIT_NOFILE` is now raised automatically to a fairly large value when possible. + This provides a minor performance benefit for large directory trees. + +- Implemented time units for `-mtime` as found in FreeBSD find ([#75]) + +[#71]: https://github.com/tavianator/bfs/issues/71 +[#75]: https://github.com/tavianator/bfs/issues/75 + + +2.2 +--- + +**March 6, 2021** + +- Fixed `-hidden` on hidden start paths + +- Added a Bash completion script. + Thanks @bmundt6! + +- Fixed rounding in `-used`. + Corresponding fixes were made to GNU find in version 4.8.0. + +- Optimized the open directory representation. + On Linux, much libc overhead is bypassed by issuing syscalls directly. + On all platforms, a few fewer syscalls and open file descriptors will be used. + +- Implemented `-flags` from BSD find + + +2.1 +--- + +**November 11, 2020** + +- Added a new `-status` option that displays the search progress in a bar at the bottom of the terminal + +- Fixed an optimizer bug introduced in version 2.0 that affected some combinations of `-user`/`-group` and `-nouser`/`-nogroup` + + +2.0 +--- + +**October 14, 2020** + +- [#8]: New `-exclude ` syntax to more easily and reliably filter out paths. + For example: + + bfs -name config -exclude -name .git + + will find all files named `config`, without searching any directories (or files) named `.git`. + In this case, the same effect could have been achieved (more awkwardly) with `-prune`: + + bfs ! \( -name .git -prune \) -name config + + But `-exclude` will work in more cases: + + # -exclude works with -depth, while -prune doesn't: + bfs -depth -name config -exclude -name .git + + # -exclude applies even to paths below the minimum depth: + bfs -mindepth 3 -name config -exclude -name .git + +- [#30]: `-nohidden` is now equivalent to `-exclude -hidden`. + This changes the behavior of command lines like + + bfs -type f -nohidden + + to do what was intended. + +- Optimized the iterative deepening (`-S ids`) implementation + +- Added a new search strategy: exponential deepening search (`-S eds`). + This strategy provides many of the benefits of iterative deepening, but much faster due to fewer re-traversals. + +- Fixed an optimizer bug that could skip `-empty`/`-xtype` if they didn't always lead to an action + +- Implemented `-xattrname` to find files with a particular extended attribute (from macOS find) + +- Made `-printf %l` still respect the width specifier (e.g. `%10l`) for non-links, to match GNU find + +- Made `bfs` fail if `-color` is given explicitly and `LS_COLORS` can't be parsed, rather than falling back to non-colored output + +[#8]: https://github.com/tavianator/bfs/issues/8 +[#30]: https://github.com/tavianator/bfs/issues/30 + + +1.* +=== + +1.7 +--- + +**April 22, 2020** + +- Fixed `-ls` printing numeric IDs instead of user/group names in large directory trees +- Cached the user and group tables for a performance boost +- Fixed interpretation of "default" ACLs +- Implemented `-s` flag to sort results + + +1.6 +--- + +**February 25, 2020** + +- Implemented `-newerXt` (explicit reference times), `-since`, `-asince`, etc. +- Fixed `-empty` to skip special files (pipes, devices, sockets, etc.) + + +1.5.2 +----- + +**January 9, 2020** + +- Fixed the build on NetBSD +- Added support for NFSv4 ACLs on FreeBSD +- Added a `+` after the file mode for files with ACLs in `-ls` +- Supported more file types (whiteouts, doors) in symbolic modes for `-ls`/`-printf %M` +- Implemented `-xattr` on FreeBSD + + +1.5.1 +----- + +**September 14, 2019** + +- Added a warning to `-mount`, since it will change behaviour in the next POSIX revision +- Added a workaround for environments that block `statx()` with `seccomp()`, like older Docker +- Fixed coloring of nonexistent leading directories +- Avoided calling `stat()` on all mount points at startup + + +1.5 +--- + +**June 27, 2019** + +- New `-xattr` predicate to find files with extended attributes +- Fixed the `-acl` implementation on macOS +- Implemented depth-first (`-S dfs`) and iterative deepening search (`-S ids`) +- Piped `-help` output into `$PAGER` by default +- Fixed crashes on some invalid `LS_COLORS` values + + +1.4.1 +----- + +**April 5, 2019** + +- Added a nicer error message when the tests are run as root +- Fixed detection of comparison expressions with signs, to match GNU find for things like `-uid ++10` +- Added support for https://no-color.org/ +- Decreased the number of `stat()` calls necessary in some cases + + +1.4 +--- + +**April 15, 2019** + +- New `-unique` option that filters out duplicate files ([#48]) +- Optimized the file coloring implementation +- Fixed the coloring implementation to match GNU ls more closely in many corner cases + - Implemented escape sequence parsing for `LS_COLORS` + - Implemented `ln=target` for coloring links like their targets + - Fixed the order of fallbacks used when some color keys are unset +- Add a workaround for incorrect file types for bind-mounted files on Linux ([#37]) + +[#48]: https://github.com/tavianator/bfs/issues/48 +[#37]: https://github.com/tavianator/bfs/issues/37 + + +1.3.3 +----- + +**February 10, 2019** + +- Fixed unpredictable behaviour for empty responses to `-ok`/`-okdir` caused by an uninitialized string +- Writing to standard output now causes `bfs` to fail if the descriptor was closed +- Fixed incomplete file coloring in error messages +- Added some data flow optimizations +- Fixed `-nogroup`/`-nouser` in big directory trees +- Added `-type w` for whiteouts, as supported by FreeBSD `find` +- Re-wrote the `-help` message and manual page + + +1.3.2 +----- + +**January 11, 2019** + +- Fixed an out-of-bounds read if LS_COLORS doesn't end with a `:` +- Allowed multiple debug flags to be specified like `-D opt,tree` + + +1.3.1 +----- + +**January 3, 2019** + +- Fixed some portability problems affecting FreeBSD + + +1.3 +--- + +**January 2, 2019** + +New features: + +- `-acl` finds files with non-trivial Access Control Lists (from FreeBSD) +- `-capable` finds files with capabilities set +- `-D all` turns on all debugging flags at once + +Fixes: + +- `LS_COLORS` handling has been improved: + - Extension colors are now case-insensitive like GNU `ls` + - `or` (orphan) and `mi` (missing) files are now treated differently + - Default colors can be unset with `di=00` or similar + - Specific colors fall back to more general colors when unspecified in more places + - `LS_COLORS` no longer needs a trailing colon +- `-ls`/`-fls` now prints the major/minor numbers for device nodes +- `-exec ;` is rejected rather than segfaulting +- `bfs` now builds on old Linux versions that require `-lrt` for POSIX timers +- For files whose access/change/modification times can't be read, `bfs` no longer fails unless those times are needed for tests +- The testsuite is now more correct and portable + + +1.2.4 +----- + +**September 24, 2018** + +- GNU find compatibility fixes for `-printf`: + - `%Y` now prints `?` if an error occurs resolving the link + - `%B` is now supported for birth/creation time (as well as `%W`/`%w`) + - All standard `strftime()` formats are supported, not just the ones from the GNU find manual +- Optimizations are now re-run if any expressions are reordered +- `-exec` and friends no longer leave zombie processes around when `exec()` fails + + +1.2.3 +----- + +**July 15, 2018** + +- Fixed `test_depth_error` on filesystems that don't fill in `d_type` +- Fixed the build on Linux architectures that don't have the `statx()` syscall (ia64, sh4) +- Fixed use of AT_EMPTY_PATH for fstatat on systems that don't support it (Hurd) +- Fixed `ARG_MAX` accounting on architectures with large pages (ppc64le) +- Fixed the build against the upcoming glibc 2.28 release that includes its own `statx()` wrapper + + +1.2.2 +----- + +**June 23, 2018** + +- Minor bug fixes: + - Fixed `-exec ... '{}' +` argument size tracking after recovering from `E2BIG` + - Fixed `-fstype` if `/proc` is available but `/etc/mtab` is not + - Fixed an uninitialized variable when given `-perm +rw...` + - Fixed some potential "error: 'path': Success" messages +- Reduced reliance on GNU coreutils in the testsuite +- Refactored and simplified the internals of `bftw()` + + +1.2.1 +----- + +**February 8, 2018** + +- Performance optimizations + + +1.2 +--- + +**January 20, 2018** + +- Added support for the `-perm +7777` syntax deprecated by GNU find (equivalent to `-perm /7777`), for compatibility with BSD finds +- Added support for file birth/creation times on platforms that report it + - `-Bmin`/`-Btime`/`-Bnewer` + - `B` flag for `-newerXY` + - `%w` and `%Wk` directives for `-printf` + - Uses the `statx(2)` system call on new enough Linux kernels +- More robustness to `E2BIG` added to the `-exec` implementation + + +1.1.4 +----- + +**October 27, 2017** + +- Added a man page +- Fixed cases where multiple actions write to the same file +- Report errors that occur when closing files/flushing streams +- Fixed "argument list too long" errors with `-exec ... '{}' +` + + +1.1.3 +----- + +**October 4, 2017** + +- Refactored the optimizer +- Implemented data flow optimizations + + +1.1.2 +----- + +**September 10, 2017** + +- Fixed `-samefile` and similar predicates when passed broken symbolic links +- Implemented `-fstype` on Solaris +- Fixed `-fstype` under musl +- Implemented `-D search` +- Implemented a cost-based optimizer + + +1.1.1 +----- + +**August 10, 2017** + +- Re-licensed under the BSD Zero Clause License +- Fixed some corner cases with `-exec` and `-ok` parsing + + +1.1 +--- + +**July 22, 2017** + +- Implemented some primaries from NetBSD `find`: + - `-exit [STATUS]` (like `-quit`, but with an optional explicit exit status) + - `-printx` (escape special characters for `xargs`) + - `-rm` (alias for `-delete`) +- Warn if `-prune` will have no effect due to `-depth` +- Handle y/n prompts according to the user's locale +- Prompt the user to correct typos without having to re-run `bfs` +- Fixed handling of paths longer than `PATH_MAX` +- Fixed spurious "Inappropriate ioctl for device" errors when redirecting `-exec ... +` output +- Fixed the handling of paths that treat a file as a directory (e.g. `a/b/c` where `a/b` is a regular file) +- Fixed an expression optimizer bug that broke command lines like `bfs -name '*' -o -print` + + +1.0.2 +----- + +**June 15, 2017** + +Bugfix release. + +- Fixed handling of \0 inside -printf format strings +- Fixed `-perm` interpretation of permcopy actions (e.g. `u=rw,g=r`) + + +1.0.1 +----- + +**May 17, 2017** + +Bugfix release. + +- Portability fixes that mostly affect GNU Hurd +- Implemented `-D exec` +- Made `-quit` not disable the implicit `-print` + + +1.0 +--- + +**April 24, 2017** + +This is the first release of bfs with support for all of GNU find's primitives. + +Changes since 0.96: + +- Implemented `-fstype` +- Implemented `-exec/-execdir ... +` +- Implemented BSD's `-X` +- Fixed the tests under Bash 3 (mostly for macOS) +- Some minor optimizations and fixes + + +0.* +=== + + +0.96 +---- + +**March 11, 2017** + +73/76 GNU find features supported. + +- Implemented -nouser and -nogroup +- Implemented -printf and -fprintf +- Implemented -ls and -fls +- Implemented -type with multiple types at once (e.g. -type f,d,l) +- Fixed 32-bit builds +- Fixed -lname on "symlinks" in Linux /proc +- Fixed -quit to take effect as soon as it's reached +- Stopped redirecting standard input from /dev/null for -ok and -okdir, as that violates POSIX +- Many test suite improvements + + +0.88 +---- + +**December 20, 2016** + +67/76 GNU find features supported. + +- Fixed the build on macOS, and some other UNIXes +- Implemented `-regex`, `-iregex`, `-regextype`, and BSD's `-E` +- Implemented `-x` (same as `-mount`/`-xdev`) from BSD +- Implemented `-mnewer` (same as `-newer`) from BSD +- Implemented `-depth N` from BSD +- Implemented `-sparse` from FreeBSD +- Implemented the `T` and `P` suffices for `-size`, for BSD compatibility +- Added support for `-gid NAME` and `-uid NAME` as in BSD + + +0.84.1 +------ + +**November 24, 2016** + +Bugfix release. + +- Fixed [#7] again +- Like GNU find, don't print warnings by default if standard input is not a terminal +- Redirect standard input from /dev/null for -ok and -okdir +- Skip . when -delete'ing +- Fixed -execdir when the root path has no slashes +- Fixed -execdir in / +- Support -perm +MODE for symbolic modes +- Fixed the build on FreeBSD + +[#7]: https://github.com/tavianator/bfs/issues/7 + + +0.84 +---- + +**October 29, 2016** + +64/76 GNU find features supported. + +- Spelling suggestion improvements +- Handle `--` +- (Untested) support for exotic file types like doors, ports, and whiteouts +- Improved robustness in the face of closed std{in,out,err} +- Fixed the build on macOS +- Implement `-ignore_readdir_race`, `-noignore_readdir_race` +- Implement `-perm` + + +0.82 +---- + +**September 4, 2016** + +62/76 GNU find features supported. + +- Rework optimization levels + - `-O1` + - Simple boolean simplification + - `-O2` + - Purity-based optimizations, allowing side-effect-free tests like `-name` or `-type` to be moved or removed + - `-O3` (**default**): + - Re-order tests to reduce the expected cost (TODO) + - `-O4` + - Aggressive optimizations that may have surprising effects on warning/error messages and runtime, but should not otherwise affect the results + - `-Ofast`: + - Always the highest level, currently the same as `-O4` +- Color files with multiple hard links correctly +- Treat `-`, `)`, and `,` as paths when required to by POSIX + - `)` and `,` are only supported before the expression begins +- Implement `-D opt` +- Implement `-D rates` +- Implement `-fprint` +- Implement `-fprint0` +- Implement BSD's `-f` +- Suggest fixes for typo'd arguments + +0.79 +---- + +**May 27, 2016** + +60/76 GNU find features supported. + +- Remove an errant debug `printf()` from `-used` +- Implement the `{} ;` variants of `-exec`, `-execdir`, `-ok`, and `-okdir` + + +0.74 +---- + +**March 12, 2016** + +56/76 GNU find features supported. + +- Color broken symlinks correctly +- Fix [#7] +- Fix `-daystart`'s rounding of midnight +- Implement (most of) `-newerXY` +- Implement `-used` +- Implement `-size` + +[#7]: https://github.com/tavianator/bfs/issues/7 + + +0.70 +---- + +**February 23, 2016** + +53/76 GNU find features supported. + +- New `make install` and `make uninstall` targets +- Squelch non-positional warnings for `-follow` +- Reduce memory footprint by as much as 64% by closing `DIR*`s earlier +- Speed up `bfs` by ~5% by using a better FD cache eviction policy +- Fix infinite recursion when evaluating `! expr` +- Optimize unused pure expressions (e.g. `-empty -a -false`) +- Optimize double-negation (e.g. `! ! -name foo`) +- Implement `-D stat` and `-D tree` +- Implement `-O` + + +0.67 +---- + +**February 14, 2016** + +Initial release. + +51/76 GNU find features supported. diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md new file mode 100644 index 0000000..77e8e2c --- /dev/null +++ b/docs/CONTRIBUTING.md @@ -0,0 +1,167 @@ +Contributing +============ + +License +------- + +`bfs` is licensed under the [Zero-Clause BSD License](https://opensource.org/licenses/0BSD), a maximally permissive license. +Contributions must use the same license. + + +Building +-------- + +`bfs` uses [GNU Make](https://www.gnu.org/software/make/) as its build system. +A simple invocation of + + $ make + +should build `bfs` successfully, with no additional steps necessary. +As usual with `make`, you can run a [parallel build](https://www.gnu.org/software/make/manual/html_node/Parallel.html) with `-j`. +For example, to use all your cores, run `make -j$(nproc)`. + +### Targets + +| Command | Description | +|------------------|---------------------------------------------------------------| +| `make` | Builds just the `bfs` binary | +| `make all` | Builds everything, including the tests (but doesn't run them) | +| `make check` | Builds everything, and runs the tests | +| `make install` | Installs `bfs` (with man page, shell completions, etc.) | +| `make uninstall` | Uninstalls `bfs` | + +### Flag-like targets + +The build system provides a few shorthand targets for handy configurations: + +| Command | Description | +|----------------|-------------------------------------------------------------| +| `make release` | Build `bfs` with optimizations, LTO, and without assertions | +| `make asan` | Enable [AddressSanitizer] | +| `make lsan` | Enable [LeakSanitizer] | +| `make msan` | Enable [MemorySanitizer] | +| `make tsan` | Enable [ThreadSanitizer] | +| `make ubsan` | Enable [UndefinedBehaviorSanitizer] | +| `make gcov` | Enable [code coverage] | + +[AddressSanitizer]: https://github.com/google/sanitizers/wiki/AddressSanitizer +[LeakSanitizer]: https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer#stand-alone-mode +[MemorySanitizer]: https://github.com/google/sanitizers/wiki/MemorySanitizer +[ThreadSanitizer]: https://github.com/google/sanitizers/wiki/ThreadSanitizerCppManual +[UndefinedBehaviorSanitizer]: https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html +[code coverage]: https://gcc.gnu.org/onlinedocs/gcc/Gcov.html + +You can combine multiple flags and other targets (e.g. `make asan ubsan check`), but not all of them will work together. + +### Flags + +Other flags are controlled with `make` variables and/or environment variables. +Here are some of the common ones; check the [`Makefile`](/Makefile) for more. + +| Flag | Description | +|----------------------------------|---------------------------------------------| +| `CC` | The C compiler to use, e.g. `make CC=clang` | +| `CFLAGS`
`EXTRA_CFLAGS` | Override/add to the default compiler flags | +| `LDFLAGS`
`EXTRA_LDFLAGS` | Override/add to the linker flags | +| `WITH_ACL`
`WITH_ATTR`
... | Enable/disable optional dependencies | +| `TEST_FLAGS` | `tests.sh` flags for `make check` | +| `DESTDIR` | The root directory for `make install` | +| `PREFIX` | The installation prefix (default: `/usr`) | +| `MANDIR` | The man page installation directory | + +### Dependency tracking + +The build system automatically tracks header dependencies with the `-M` family of compiler options (see `DEPFLAGS` in the `Makefile`). +So if you edit a header file, `make` will rebuild the necessary object files ensuring they don't go out of sync. + +We go one step further than most build systems by tracking the flags that were used for the previous compilation. +That means you can change configurations without having to `make clean`. +For example, + + $ make + $ make release + +will build the project in debug mode and then rebuild it in release mode. + +A side effect of this may be surprising: `make check` by itself will rebuild the project in the default configuration. +To test a different configuration, you'll have to repeat it (e.g. `make release check`). + + +Testing +------- + +`bfs` comes with an extensive testsuite which can be run with + + $ make check + +Most of the testsuite is implemented in the file [`tests.sh`](/tests.sh). +This script contains hundreds of separate test cases. +Most of them are *snapshot tests* which compare `bfs`'s output to a known-good copy saved under [`tests`](/tests). + +You can pass the name of a particular test case (or a few) to run just those tests. +For example: + + $ ./tests.sh test_basic + +If you need to update the reference snapshot, pass `--update`. +It can be handy to generate the snapshot with a different `find` implementation to ensure the output is correct, for example: + + $ ./tests.sh test_basic --bfs=find --update + +But keep in mind, other `find` implementations may not be correct. +To my knowledge, no other implementation passes even the POSIX-compatible subset of the tests: + + $ ./tests.sh --bfs=find --posix + ... + tests passed: 89 + tests failed: 5 + +Run + + $ ./tests.sh --help + +for more details. + +### Validation + +A more thorough testsuite is run by the [CI](https://github.com/tavianator/bfs/actions) and to validate releases. +It builds `bfs` in multiple configurations to test for latent bugs, memory leaks, 32-bit compatibility, etc. +You can run it yourself with + + $ make distcheck + +Some of these tests require `sudo`, and will prompt for your password if necessary. + + +Hacking +------- + +`bfs` is written in [C](https://en.wikipedia.org/wiki/C_(programming_language)), specifically [C11](https://en.wikipedia.org/wiki/C11_(C_standard_revision)). +You can get a feel for the coding style by skimming the source code. +[`main.c`](/src/main.c) contains an overview of the rest of source files. +A quick summary: + +- Tabs for indentation, spaces for alignment. +- Most types and functions should be namespaced with `bfs_`. + Exceptions are made for things that could be generally useful outside of `bfs`. +- Error handling follows the C standard library conventions: return a nonzero `int` or a `NULL` pointer, with the error code in `errno`. + All failure cases should be handled, including `malloc()` failures. +- `goto` is not harmful for cleaning up in error paths. + +### Adding tests + +Both new features and bug fixes should have associated tests. +To add a test, create a new function in `tests.sh` called `test_`. +Snapshot tests use the `bfs_diff` function to automatically compare the generated and expected outputs. +For example, + +```bash +function test_something() { + bfs_diff basic -name something +} +``` + +`basic` is one of the directory trees generated for test cases; others include `links`, `loops`, `deep`, and `rainbow`. + +Run `./tests.sh test_something --update` to generate the reference snapshot (and don't forget to `git add` it). +Finally, add the test case to one of the arrays `posix_tests`, `bsd_tests`, `gnu_tests`, or `bfs_tests` depending on which `find` implementations it should be compatible with. diff --git a/docs/bfs.1 b/docs/bfs.1 new file mode 100644 index 0000000..53a9831 --- /dev/null +++ b/docs/bfs.1 @@ -0,0 +1,811 @@ +.TH BFS 1 +.SH NAME +bfs \- breadth-first search for your files +.SH SYNOPSIS +.B bfs +.RB [ flags ...] +.RI [ paths ...] +.RB [ expression ...] +.PP +flags +.RB ( \-H / \-L / \-P +etc.), +.IR paths , +and +.B expressions +may be freely mixed in any order. +.SH DESCRIPTION +.B bfs +is a breadth-first version of the UNIX +.BR find (1) +command. +.PP +.B bfs +supports almost every feature from every major +.BR find (1) +implementation, so your existing command lines should work as-is. +It also adds some features of its own, such as a more forgiving command line parser and some additional options. +.PP +Each +.I path +specified on the command line is treated as a starting path to search through. +If no paths are specified, the current directory +.RI ( . ) +is searched by default. +.PP +Like +.BR find (1), +.B bfs +interprets its arguments as a short-circuiting Boolean expression. +For example, +.PP +.nf +.RS +.B bfs \\\( \-name '*.txt' \-or \-lname '*.txt' \\\\) \-and \-print +.RE +.fi +.PP +will print the all the paths that are either .txt files or symbolic links to .txt files. +.B \-and +is implied between two consecutive expressions, so this is equivalent: +.PP +.nf +.RS +.B bfs \\\( \-name '*.txt' \-or \-lname '*.txt' \\\\) \-print +.RE +.fi +.PP +Finally, +.B \-print +is implied if no actions are specified, so this too is equivalent: +.PP +.nf +.RS +.B bfs \-name '*.txt' \-or \-lname '*.txt' +.RE +.fi +.PP +Most options that take a numeric argument +.I N +will also accept +.I \-N +or +.IR +N . +.IR \-N +means "less than +.IR N ," +and +.I +N +means "greater than +.IR N ." +.SH FLAGS +.TP +.B \-H +Follow symbolic links on the command line, but not while searching. +.TP +.B \-L +Follow all symbolic links. +.TP +.B \-P +Never follow symbolic links (the default). +.TP +.B \-E +Use extended regular expressions (same as \fB\-regextype posix-extended\fR). +.TP +.B \-X +Filter out files with +.RB non- xargs (1)-safe +names. +.TP +.B \-d +Search in post-order (same as +.BR \-depth ). +.TP +.B \-s +Visit directory entries in sorted order. +The sorting takes place within each directory separately, which makes it different from +.B bfs ... | +.BR sort , +but still provides a deterministic ordering. +.TP +.B \-x +Don't descend into other mount points (same as \fB\-xdev\fR). +.TP +\fB\-f \fIPATH\fR +Treat +.I PATH +as a path to search (useful if it begins with a dash). +.PP +.TP +\fB\-D \fIFLAG\fR +Turn on a debugging flag (see +.B \-D +.IR help ). +.PP +\fB\-O\fIN\fR +.RS +Enable optimization level +.I N +(default: +.IR 3 ). +.TP +.BI \-O 0 +Disable all optimizations. +.TP +.BI \-O 1 +Basic logical simplifications. +.TP +.BI \-O 2 +All +.BI \-O 1 +optimizations, plus dead code elimination and data flow analysis. +.TP +.BI \-O 3 +All +.BI \-O 2 +optimizations, plus re-order expressions to reduce expected cost. +.TP +\fB\-O\fI4\fR/\fB\-O\fIfast\fR +All optimizations, including aggressive optimizations that may alter the observed behavior in corner cases. +.RE +.PP +\fB\-S \fIbfs\fR|\fIdfs\fR|\fIids\fR|\fIeds\fR +.RS +Choose the search strategy. +.TP +.I bfs +Breadth-first search (the default). +.TP +.I dfs +Depth-first search. +Uses less memory than breadth-first search, but is typically slower to return relevant results. +.TP +.I ids +Iterative deepening search. +Performs repeated depth-first searches with increasing depth limits. +This gives results in the same order as breadth-first search, but with the reduced memory consumption of depth-first search. +Tends to be very slow in practice, so use it only if you absolutely need breadth-first ordering, but +.B \-S +.I bfs +consumes too much memory. +.TP +.I eds +Exponential deepening search. +A compromise between breadth- and depth-first search, which searches exponentially increasing depth ranges (e.g 0-1, 1-2, 2-4, 4-8, etc.). +Provides many of the benefits of breadth-first search with depth-first's reduced memory consumption. +Typically far faster than +.B \-S +.IR ids . +.RE +.SH OPERATORS +.TP +\fB( \fIexpression \fB)\fR +Parentheses are used for grouping expressions together. +You'll probably have to write +.B \\\\( +.I expression +.B \\\\) +to avoid the parentheses being interpreted by the shell. +.PP +\fB! \fIexpression\fR +.br +\fB\-not \fIexpression\fR +.RS +The "not" operator: returns the negation of the truth value of the +.IR expression . +You may have to write \fB\\! \fIexpression\fR to avoid \fB!\fR being interpreted by the shell. +.RE +.PP +\fIexpression\fR \fIexpression\fR +.br +\fIexpression \fB\-a \fIexpression\fR +.br +\fIexpression \fB\-and \fIexpression\fR +.RS +Short-circuiting "and" operator: if the left-hand +.I expression +is +.BR true , +returns the right-hand +.IR expression ; +otherwise, returns +.BR false . +.RE +.PP +\fIexpression \fB\-o \fIexpression\fR +.br +\fIexpression \fB\-or \fIexpression\fR +.RS +Short-circuiting "or" operator: if the left-hand +.I expression +is +.BR false , +returns the right-hand +.IR expression ; +otherwise, returns +.BR true . +.RE +.TP +\fIexpression \fB, \fIexpression\fR +The "comma" operator: evaluates the left-hand +.I expression +but discards the result, returning the right-hand +.IR expression . +.SH SPECIAL FORMS +.TP +\fB\-exclude \fIexpression\fR +Exclude all paths matching the +.I expression +from the search. +This is more powerful than +.BR \-prune , +because it applies even when the expression wouldn't otherwise be evaluated, due to +.B \-depth +or +.B \-mindepth +for example. +Exclusions are always applied before other expressions, so it may be least confusing to put them first on the command line. +.SH OPTIONS +.PP +.B \-color +.br +.B \-nocolor +.RS +Turn colors on or off (default: +.B \-color +if outputting to a terminal, +.B \-nocolor +otherwise). +.RE +.TP +.B \-daystart +Measure time relative to the start of today. +.TP +.B \-depth +Search in post-order (descendents first). +.TP +.B \-follow +Follow all symbolic links (same as +.BR \-L ). +.TP +\fB\-files0\-from \fIFILE\fR +Treat the NUL ('\\0')-separated paths in +.I FILE +as starting points for the search. +Pass +.B \-files0\-from +.I \- +to read the paths from standard input. +.PP +\fB\-ignore_readdir_race\fR +.br +\fB\-noignore_readdir_race\fR +.RS +Whether to report an error if +.B bfs +detects that the file tree is modified during the search (default: +.BR \-noignore_readdir_race ). +.RE +.PP +\fB\-maxdepth \fIN\fR +.br +\fB\-mindepth \fIN\fR +.RS +Ignore files deeper/shallower than +.IR N . +.RE +.TP +.B \-mount +Don't descend into other mount points (same as +.B \-xdev +for now, but will skip mount points entirely in the future). +.TP +.B \-nohidden +Exclude hidden files and directories. +.TP +.B \-noleaf +Ignored; for compatibility with GNU find. +.TP +\fB\-regextype \fITYPE\fR +Use +.IR TYPE -flavored +regexes (default: +.IR posix-basic ; +see +.B \-regextype +.IR help ). +.TP +.B \-status +Display a status bar while searching. +.TP +.B \-unique +Skip any files that have already been seen. +Particularly useful along with +.BR \-L . +.PP +.B \-warn +.br +.B \-nowarn +.RS +Turn on or off warnings about the command line. +.RE +.TP +.B \-xdev +Don't descend into other mount points. +.SH TESTS +.TP +.B \-acl +Find files with a non-trivial Access Control List +.RB ( acl (5)). +.PP +\fB\-amin\fR [\fI\-+\fR]\fIN\fR +.br +\fB\-Bmin\fR [\fI\-+\fR]\fIN\fR +.br +\fB\-cmin\fR [\fI\-+\fR]\fIN\fR +.br +\fB\-mmin\fR [\fI\-+\fR]\fIN\fR +.RS +Find files +.BR a ccessed/ B irthed/ c hanged/ m odified +.I N +minutes ago. +.RE +.PP +\fB\-anewer \fIFILE\fR +.br +\fB\-Bnewer \fIFILE\fR +.br +\fB\-cnewer \fIFILE\fR +.br +\fB\-mnewer \fIFILE\fR +.RS +Find files +.BR a ccessed/ B irthed/ c hanged/ m odified +more recently than +.I FILE +was modified. +.RE +.PP +\fB\-asince \fITIME\fR +.br +\fB\-Bsince \fITIME\fR +.br +\fB\-csince \fITIME\fR +.br +\fB\-msince \fITIME\fR +.RS +Find files +.BR a ccessed/ B irthed/ c hanged/ m odified +more recently than the ISO 8601-style timestamp +.IR TIME . +See +.BI \-newer XY +for examples of the timestamp format. +.RE +.PP +\fB\-atime\fR [\fI\-+\fR]\fIN\fR +.br +\fB\-Btime\fR [\fI\-+\fR]\fIN\fR +.br +\fB\-ctime\fR [\fI\-+\fR]\fIN\fR +.br +\fB\-mtime\fR [\fI\-+\fR]\fIN\fR +.RS +Find files +.BR a ccessed/ B irthed/ c hanged/ m odified +.I N +days ago. +.RE +.TP +.B \-capable +Find files with POSIX.1e +.BR capabilities (7) +set. +.TP +\fB\-depth\fR [\fI\-+\fR]\fIN\fR +Find files with depth +.IR N . +.TP +.B \-empty +Find empty files/directories. +.PP +.B \-executable +.br +.B \-readable +.br +.B \-writable +.RS +Find files the current user can execute/read/write. +.RE +.PP +.B \-false +.br +.B \-true +.RS +Always false/true. +.RE +.TP +.B \-fstype TYPE +Find files on file systems with the given +.BR TYPE . +.PP +\fB\-gid\fR [\fI\-+\fR]\fIN\fR +.br +\fB\-uid\fR [\fI\-+\fR]\fIN\fR +.RS +Find files owned by group/user ID +.IR N . +.RE +.PP +\fB\-group \fINAME\fR +.br +\fB\-user \fINAME\fR +.RS +Find files owned by the group/user +.IR NAME . +.RE +.TP +.B \-hidden +Find hidden files (those beginning with +.IR . ). +.PP +\fB\-ilname \fIGLOB\fR +.br +\fB\-iname \fIGLOB\fR +.br +\fB\-ipath \fIGLOB\fR +.br +\fB\-iregex \fIREGEX\fR +.br +\fB\-iwholename \fIGLOB\fR +.RS +Case-insensitive versions of +.BR \-lname / \-name / \-path / \-regex / \-wholename . +.RE +.TP +\fB\-inum\fR [\fI\-+\fR]\fIN\fR +Find files with inode number +.IR N . +.TP +\fB\-links\fR [\fI\-+\fR]\fIN\fR +Find files with +.I N +hard links. +.TP +\fB\-lname \fIGLOB\fR +Find symbolic links whose target matches the +.IR GLOB . +.TP +\fB\-name \fIGLOB\fR +Find files whose name matches the +.IR GLOB . +.TP +\fB\-newer \fIFILE\fR +Find files newer than +.IR FILE . +.TP +\fB\-newer\fIXY \fIREFERENCE\fR +Find files whose +.I X +time is newer than the +.I Y +time of +.IR REFERENCE . +.I X +and +.I Y +can be any of +.RI [ aBcm ] +.RI ( a ccess/ B irth/ c hange/ m odification). +.I Y +may also be +.I t +to parse +.I REFERENCE +as an ISO 8601-style timestamp. For example: +.PP +.RS +1991-12-14 +.br +1991-12-14T03:00 +.br +1991-12-14T03:00-07:00 +.br +1991-12-14T10:00Z +.RE +.PP +.B \-nogroup +.br +.B \-nouser +.RS +Find files owned by nonexistent groups/users. +.RE +.PP +\fB\-path \fIGLOB\fR +.br +\fB\-wholename \fIGLOB\fR +.RS +Find files whose entire path matches the +.IR GLOB . +.RE +.TP +\fB\-perm\fR [\fI\-\fR]\fIMODE\fR +Find files with a matching mode. +.TP +\fB\-regex \fIREGEX\fR +Find files whose entire path matches the regular expression +.IR REGEX . +.TP +\fB\-samefile \fIFILE\fR +Find hard links to +.IR FILE . +.TP +\fB\-since \fITIME\fR +Find files modified since the ISO 8601-style timestamp +.IR TIME . +See +.BI \-newer XY +for examples of the timestamp format. +.TP +\fB\-size\fR [\fI\-+\fR]\fIN\fR[\fIcwbkMGTP\fR] +Find files with the given size, in 1-byte +.IR c haracters, +2-byte +.IR w ords, +512-byte +.IR b locks +(default), or +.IR k iB/ M iB/ G iB/ T iB/ P iB. +.TP +.B \-sparse +Find files that occupy fewer disk blocks than expected. +.TP +\fB\-type\fR [\fIbcdlpfswD\fR] +Find files of the given type. +Possible types are +.IR b lock +device, +.IR c haracter +device, +.IR d irectory, +symbolic +.IR l ink, +.IR p ipe, +regular +.IR f ile, +.IR s ocket, +.IR w hiteout, +and +.IR D oor. +.TP +\fB\-used\fR [\fI\-+\fR]\fIN\fR +Find files last accessed +.I N +days after they were changed. +.TP +.B \-xattr +Find files with extended attributes +.RB ( xattr (7)). +.TP +\fB\-xattrname\fR \fINAME\fR +Find files with the extended attribute +.IR NAME . +.TP +\fB\-xtype\fR [\fIbcdlpfswD\fR] +Find files of the given type, following links when +.B \-type +would not, and vice versa. +.SH ACTIONS +.PP +.B \-delete +.br +.B \-rm +.RS +Delete any found files (implies \fB-depth\fR). +.RE +.TP +\fB\-exec \fIcommand ... {} ;\fR +Execute a command. +.TP +\fB\-exec \fIcommand ... {} +\fR +Execute a command with multiple files at once. +.TP +\fB\-ok \fIcommand ... {} ;\fR +Prompt the user whether to execute a command. +.PP +\fB\-execdir \fIcommand ... {} ;\fR +.br +\fB\-execdir \fIcommand ... {} +\fR +.br +\fB\-okdir \fIcommand ... {} ;\fR +.RS +Like +.BR \-exec / \-ok , +but run the command in the same directory as the found file(s). +.RE +.TP +\fB\-exit\fR [\fISTATUS\fR] +Exit immediately with the given status (0 if unspecified). +.PP +\fB\-fls \fIFILE\fR +.br +\fB\-fprint \fIFILE\fR +.br +\fB\-fprint0 \fIFILE\fR +.br +\fB\-fprintf \fIFILE FORMAT\fR +.RS +Like +.BR \-ls / \-print / \-print0 / \-printf , +but write to +.I FILE +instead of standard output. +.RE +.TP +.B \-ls +List files like +.B ls +.IR \-dils . +.TP +.B \-print +Print the path to the found file. +.TP +.B \-print0 +Like +.BR \-print , +but use the null character ('\\0') as a separator rather than newlines. +Useful in conjunction with +.B xargs +.IR \-0 . +.TP +\fB\-printf \fIFORMAT\fR +Print according to a format string (see +.BR find (1)). +These additional format directives are supported: +.RS +.TP +%w +The file's birth time, in the same format as %a/%c/%t. +.TP +.RI %W k +Field +.I k +of the file's birth time, in the same format as +.RI %A k /%C k /%T k . +.RE +.TP +.B \-printx +Like +.BR \-print , +but escape whitespace and quotation characters, to make the output safe for +.BR xargs (1). +Consider using +.B \-print0 +and +.B xargs +.I \-0 +instead. +.TP +.B \-prune +Don't descend into this directory. +.TP +.B \-quit +Quit immediately. +.TP +.B \-version +Print version information. +.TP +.B \-help +Print usage information. +.SH ENVIRONMENT +Certain environment variables affect the behavior of +.BR bfs . +.PP +.B LANG +.br +.B LC_* +.RS +Specifies the +.BR locale (7) +in use for various things. +.B bfs +is not (yet) translated to any languages except English, but the locale will still affect the format of printed values. +Yes/no prompts (e.g. from +.BR \-ok ) +will also be interpreted according to the current locale. +.RE +.PP +.B LS_COLORS +.br +.B BFS_COLORS +.RS +Controls the colors used when displaying file paths if +.B \-color +is enabled. +.B bfs +interprets +.B LS_COLORS +the same way GNU +.BR ls (1) +does (see +.BR dir_colors (5)). +.B BFS_COLORS +can be used to customize +.B bfs +without affecting other commands. +.RE +.TP +.B NO_COLOR +Causes +.B bfs +to default to +.B \-nocolor +if it is set (see https://no-color.org/). +.TP +.B PAGER +Specifies the pager used for +.B \-help +output. +Defaults to +.BR more (1). +.TP +.B POSIXLY_CORRECT +Makes +.B bfs +conform more strictly to the POSIX.1-2017 specification for +.BR find (1). +Currently this just disables warnings by default. +It does not disable +.BR bfs 's +various extensions to the base POSIX functionality. +.SH EXAMPLES +.TP +.B bfs +With no arguments, +.B bfs +prints all files under the current directory in breadth-first order. +.TP +.B bfs \-name '*.txt' +Prints all the .txt files under the current directory. +.B *.txt +is quoted to ensure the glob is processed by +.B bfs +rather than the shell. +.TP +\fBbfs \-name access_log \-L \fI/var\fR +Finds all files named +.B access_log +under +.IR /var , +following symbolic links. +.B bfs +allows flags and paths to appear anywhere on the command line. +.TP +\fBbfs \fI~ \fB\-not \-user $USER\fR +Prints all files in your home directory not owned by you. +.TP +.B bfs \-xtype l +Finds broken symbolic links. +.TP +.B bfs \-name config \-exclude \-name .git +Finds all files named +.BR config, +skipping every +.B .git +directory. +.TP +.B bfs \-type f \-executable \-exec strip '{}' + +Runs +.BR strip (1) +on all executable files it finds, passing it multiple files at a time. +.SH BUGS +https://github.com/tavianator/bfs/issues +.SH AUTHOR +Tavian Barnes +.PP +https://tavianator.com/projects/bfs.html +.SH SEE ALSO +.BR find (1), +.BR locate (1), +.BR xargs (1) -- cgit v1.2.3