summaryrefslogtreecommitdiffstats
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/BUILDING.md218
-rw-r--r--docs/CHANGELOG.md368
-rw-r--r--docs/CONTRIBUTING.md (renamed from docs/HACKING.md)4
-rw-r--r--docs/RELATED.md43
-rw-r--r--docs/SECURITY.md126
-rw-r--r--docs/USAGE.md46
-rw-r--r--docs/bfs.1217
7 files changed, 851 insertions, 171 deletions
diff --git a/docs/BUILDING.md b/docs/BUILDING.md
index b19ef00..69a997c 100644
--- a/docs/BUILDING.md
+++ b/docs/BUILDING.md
@@ -1,103 +1,157 @@
Building `bfs`
==============
-Compiling
----------
-
-`bfs` uses [GNU Make](https://www.gnu.org/software/make/) as its build system.
A simple invocation of
+ $ ./configure
$ 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)`.
+should build `bfs` successfully.
-### 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 [`GNUmakefile`](/GNUmakefile) for more.
-
-| Flag | Description |
-|----------------------------------|---------------------------------------------|
-| `CC` | The C compiler to use, e.g. `make CC=clang` |
-| `CFLAGS`<br>`EXTRA_CFLAGS` | Override/add to the default compiler flags |
-| `LDFLAGS`<br>`EXTRA_LDFLAGS` | Override/add to the linker flags |
-| `USE_ACL`<br>`USE_ATTR`<br>... | Enable/disable [optional dependencies] |
-| `TEST_FLAGS` | `tests.sh` flags for `make check` |
-| `BUILDDIR` | The build output directory (default: `.`) |
-| `DESTDIR` | The root directory for `make install` |
-| `PREFIX` | The installation prefix (default: `/usr`) |
-| `MANDIR` | The man page installation directory |
-
-[optional dependencies]: #dependencies
+Configuration
+-------------
+
+```console
+$ ./configure --help
+Usage:
+
+ $ ./configure [--enable-*|--disable-*] [--with-*|--without-*] [CC=...] [...]
+ $ make
+
+...
+```
+
+### Variables
+
+Variables set in the environment or on the command line will be picked up:
+These variables specify binaries to run during the configuration and build process:
+
+<pre>
+<b>MAKE</b>=<i>make</i>
+ <a href="https://en.wikipedia.org/wiki/Make_(software)">make</a> implementation
+<b>CC</b>=<i>cc</i>
+ C compiler
+<b>INSTALL</b>=<i>install</i>
+ Copy files during <i>make install</i>
+<b>MKDIR</b>="<i>mkdir -p</i>"
+ Create directories
+<b>PKG_CONFIG</b>=<i>pkg-config</i>
+ Detect external libraries and required build flags
+<b>RM</b>="<i>rm -f</i>"
+ Delete files
+</pre>
+
+These flags will be used by the build process:
+
+<pre>
+<b>CPPFLAGS</b>="<i>-I... -D...</i>"
+<b>CFLAGS</b>="<i>-W... -f...</i>"
+<b>LDFLAGS</b>="<i>-L... -Wl,...</i>"
+ Preprocessor/compiler/linker flags
+
+<b>LDLIBS</b>="<i>-l... -l...</i>"
+ Dynamic libraries to link
+
+<b>EXTRA_</b>{<b>CPPFLAGS</b>,<b>CFLAGS</b>,<b>LDFLAGS</b>,<b>LDLIBS</b>}="<i>...</i>"
+ Adds to the default flags, instead of replacing them
+</pre>
+
+### Build profiles
+
+The default flags result in a plain debug build.
+Other build profiles can be enabled:
+
+<pre>
+--enable-release
+ Enable optimizations, disable assertions
+
+--enable-<a href="https://github.com/google/sanitizers/wiki/AddressSanitizer">asan</a>
+--enable-<a href="https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer#stand-alone-mode">lsan</a>
+--enable-<a href="https://github.com/google/sanitizers/wiki/MemorySanitizer">msan</a>
+--enable-<a href="https://github.com/google/sanitizers/wiki/ThreadSanitizerCppManual">tsan</a>
+--enable-<a href="https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html">ubsan</a>
+ Enable sanitizers
+
+--enable-<a href="https://gcc.gnu.org/onlinedocs/gcc/gcov/introduction-to-gcov.html">gcov</a>
+ Enable code coverage instrumentation
+</pre>
+
+You can combine multiple profiles (e.g. `./configure --enable-asan --enable-ubsan`), but not all of them will work together.
### Dependencies
`bfs` depends on some system libraries for some of its features.
-These dependencies are optional, and can be turned off at build time if necessary by setting the appropriate variable to the empty string (e.g. `make USE_ONIGURUMA=`).
+External dependencies are auto-detected by default, but you can build `--with` or `--without` them explicitly:
-| Dependency | Platforms | `make` flag |
-|-------------|------------|-----------------|
-| [acl] | Linux only | `USE_ACL` |
-| [attr] | Linux only | `USE_ATTR` |
-| [libcap] | Linux only | `USE_LIBCAP` |
-| [Oniguruma] | All | `USE_ONIGURUMA` |
+<pre>
+--with-<a href="https://savannah.nongnu.org/projects/acl">libacl</a> --without-libacl
+--with-<a href="https://sites.google.com/site/fullycapable/">libcap</a> --without-libcap
+--with-<a href="https://github.com/SELinuxProject/selinux">libselinux</a> --without-libselinux
+--with-<a href="https://github.com/axboe/liburing">liburing</a> --without-liburing
+--with-<a href="https://github.com/kkos/oniguruma">oniguruma</a> --without-oniguruma
+</pre>
-[acl]: https://savannah.nongnu.org/projects/acl
-[attr]: https://savannah.nongnu.org/projects/attr
-[libcap]: https://sites.google.com/site/fullycapable/
-[Oniguruma]: https://github.com/kkos/oniguruma
+[`pkg-config`] is used, if available, to detect these libraries and any additional build flags they may require.
+If this is undesirable, disable it by setting `PKG_CONFIG` to the empty string (`./configure PKG_CONFIG=""`).
-### Dependency tracking
+[`pkg-config`]: https://www.freedesktop.org/wiki/Software/pkg-config/
-The build system automatically tracks header dependencies with the `-M` family of compiler options (see `DEPFLAGS` in the [`GNUmakefile`](/GNUmakefile)).
-So if you edit a header file, `make` will rebuild the necessary object files ensuring they don't go out of sync.
+### Out-of-tree builds
-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,
+You can set up an out-of-tree build by running the `configure` script from another directory, for example:
+ $ mkdir out
+ $ cd out
+ $ ../configure
$ 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`).
+Building
+--------
+
+### Targets
+
+The [`Makefile`](/Makefile) supports several different build targets:
+
+<pre>
+make
+ The default target; builds just the <i>bfs</i> binary
+make <b>all</b>
+ Builds everything, including the tests (but doesn't run them)
+
+make <b>check</b>
+ Builds everything, and runs all tests
+make <b>unit-tests</b>
+ Builds and runs the unit tests
+make <b>integration-tests</b>
+ Builds and runs the integration tests
+make <b>distcheck</b>
+ Builds and runs the tests in multiple different configurations
+
+make <b>install</b>
+ Installs bfs globally
+make <b>uninstall</b>
+ Uninstalls bfs
+
+make <b>clean</b>
+ Deletes all built files
+make <b>distclean</b>
+ Also deletes files generated by ./configure
+</pre>
+
+
+Troubleshooting
+---------------
+
+If the build fails or behaves unexpectedly, start by enabling verbose mode:
+
+ $ ./configure V=1
+ $ make V=1
+
+This will print the generated configuration and the exact commands that are executed.
+
+You can also check the file `gen/config.log`, which contains any errors from commands run during the configuration phase.
Testing
@@ -124,11 +178,11 @@ It can be handy to generate the snapshot with a different `find` implementation
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/tests.sh --bfs=find --posix
+ $ ./tests/tests.sh --bfs=find --sudo --posix
...
- tests passed: 90
- tests skipped: 3
- tests failed: 6
+ [PASS] 104 / 119
+ [SKIP] 1 / 119
+ [FAIL] 14 / 119
Run
diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md
index 3dca97c..3e72baf 100644
--- a/docs/CHANGELOG.md
+++ b/docs/CHANGELOG.md
@@ -1,6 +1,372 @@
+4.*
+===
+
+4.0.6
+-----
+
+**February 26, 2025**
+
+### Bug fixes
+
+- Fixed `-fstype` with btrfs subvolumes (requires Linux 5.8+)
+ ([`0dccdae`](https://github.com/tavianator/bfs/commit/0dccdae4510ff5603247be871e64a6119647ea2a))
+
+- Fixed `-ls` with timestamps very far in the future
+ ([`dd5df1f`](https://github.com/tavianator/bfs/commit/dd5df1f8997550c5bf49205578027715b957bd01))
+
+- Fixed the `posix/exec_sigmask` test on mips64el Linux
+ ([`532dec0`](https://github.com/tavianator/bfs/commit/532dec0849dcdc3e15e530ac40a8168f146a41cd))
+
+- Fixed time-related tests with `mawk 1.3.4 20250131`
+ ([#152](https://github.com/tavianator/bfs/issues/152))
+
+
+4.0.5
+-----
+
+**January 18, 2025**
+
+### Bug fixes
+
+- Fixed a bug that could cause child processes (e.g. from `-exec`) to run with all signals blocked.
+ The bug was introduced in version 3.3.
+ ([`af207e7`](https://github.com/tavianator/bfs/commit/af207e702148e5c9ae08047d7a2dce6394653b62))
+
+### Changes
+
+- Fixed the build against old liburing versions
+ ([#147](https://github.com/tavianator/bfs/issues/147))
+
+- Async I/O performance optimizations
+
+
+4.0.4
+-----
+
+**October 31, 2024**
+
+## Bug fixes
+
+- Fixed a man page typo
+ ([#144](https://github.com/tavianator/bfs/pull/144))
+
+- Fixed the build on PowerPC macOS
+ ([#145](https://github.com/tavianator/bfs/issues/145))
+
+- Fixed a bug introduced in bfs 4.0.3 that colorized every file as if it had capabilities on non-Linux systems
+ ([#146](https://github.com/tavianator/bfs/pull/146))
+
+
+4.0.3
+-----
+
+**October 22, 2024**
+
+### Bug fixes
+
+- Fixed an assertion failure when `$LS_COLORS` contained escaped NUL bytes like `*\0.gz=`
+ ([`f5eaadb9`](https://github.com/tavianator/bfs/commit/f5eaadb96fb94b2d3666e53a99495840a3099aec))
+
+- Fixed a use-after-free bug introduced in bfs 4.0 when unregistering and re-registering signal hooks.
+ This could be reproduced with `bfs -nocolor` by repeatedly sending `SIGINFO`/`SIGUSR1` to toggle the status bar.
+ ([`39ff273`](https://github.com/tavianator/bfs/commit/39ff273df97e51b1285358b9e6808b117ea8adb1))
+
+- Fixed a hang present since bfs 3.0 colorizing paths like `notdir/file`, where `notdir` is a symlink pointing to a non-directory file.
+ ([`b89f22cb`](https://github.com/tavianator/bfs/commit/b89f22cbf250958a802915eb7b6bf0e5f38376ca))
+
+
+4.0.2
+-----
+
+**September 17, 2024**
+
+### New features
+
+- Implemented `./configure --version=X.Y.Z`, mainly for packagers to override the version number
+ ([`4a278d3`](https://github.com/tavianator/bfs/commit/4a278d3e39a685379711727eac7bfaa83679e0e4))
+
+### Changes
+
+- Minor refactoring of the build system
+
+### Bug fixes
+
+- Fixed `./configure --help`, which was broken since `bfs` 4.0
+ ([`07ae989`](https://github.com/tavianator/bfs/commit/07ae98906dbb0caaac2f758d72e88dd0975b2a81))
+
+- Fixed compiler flag auto-detection on systems with non-GNU `sed`.
+ This fixes a potential race condition on FreeBSD since `bfs` 4.0 due to the [switch to `_Fork()`](https://github.com/tavianator/bfs/commit/085bb402c7b2c2f96624fb0523ff3f9686fe26d9) without passing `-z now` to the linker.
+ ([`34e6081`](https://github.com/tavianator/bfs/commit/34e60816adb0ea8ddb155a454676a99ab225dc8a))
+
+- Fixed `$MAKE distcheck` when `$MAKE` is not `make`, e.g. `gmake distcheck` on BSD
+ ([`2135b00`](https://github.com/tavianator/bfs/commit/2135b00d215efc5c2c38e1abd3254baf31229ad4))
+
+- Fixed some roff syntax issues in the `bfs` manpage
+ ([`812ecd1`](https://github.com/tavianator/bfs/commit/812ecd1feeb002252dd4d732b395d31c4179afaf))
+
+- Fixed an assertion failure optimizing expressions like `bfs -not \( -prune , -type f \)` since `bfs` 3.1.
+ Release builds were not affected, since their assertions are disabled and the behaviour was otherwise correct.
+ ([`b1a9998`](https://github.com/tavianator/bfs/commit/b1a999892b9e13181ddd9a7d895f3d1c65fbb449))
+
+
+4.0.1
+-----
+
+**August 19, 2024**
+
+### Bug fixes
+
+- `bfs` no longer prints a "suppressed errors" warning unless `-noerror` is actually suppressing errors
+ ([`5d03c9d`](https://github.com/tavianator/bfs/commit/5d03c9d460d1c1afcdf062d494537986ce96a690))
+
+
+4.0
+---
+
+**August 16, 2024**
+
+### New features
+
+- To match BSD `find` (and the POSIX Utility Syntax Guidelines), multiple flags can now be given in a single argument like `-LEXO2`.
+ Previously, you would have had to write `-L -E -X -O2`.
+ ([`c0fd33a`](https://github.com/tavianator/bfs/commit/c0fd33aaef5f345566a41c7c2558f27adf05558b))
+
+- Explicit timestamps can now be written as `@SECONDS_SINCE_EPOCH`.
+ For example, `bfs -newermt @946684800` will print files modified since January 1, 2000 (UTC).
+ ([`c6bb003`](https://github.com/tavianator/bfs/commit/c6bb003b8882e9a16941f5803d072ec1cb728318))
+
+- The new `-noerror` option suppresses all error messages during traversal.
+ ([#142](https://github.com/tavianator/bfs/issues/142))
+
+### Changes
+
+- `-mount` now excludes mount points entirely, to comply with the recently published POSIX 2024 standard.
+ Use `-xdev` to include the mount point itself, but not its contents.
+ `bfs` has been warning about this change since version 1.5.1 (September 2019).
+ ([`33b85e1`](https://github.com/tavianator/bfs/commit/33b85e1f8769e7f75721887638ae454d109a034f))
+
+- `-perm` now takes the current file creation mask into account when parsing a symbolic mode like `+rw`, as clarified by [POSIX defect 1392](https://www.austingroupbugs.net/view.php?id=1392).
+ This matches the behaviour of BSD `find`, contrary to the behaviour of GNU `find`.
+ ([`6290ce4`](https://github.com/tavianator/bfs/commit/6290ce41f3ec1f889abb881cf90ca91da869b5b2))
+
+### Bug fixes
+
+- Fixed commands like `./configure CC=clang --enable-release` that set variables before other options
+ ([`49a5d48`](https://github.com/tavianator/bfs/commit/49a5d48d0a43bac313c8b8d1b167e60da9eaadf6))
+
+- Fixed the build on RISC-V with GCC versions older than 14
+ ([`e93a1dc`](https://github.com/tavianator/bfs/commit/e93a1dccd82f831a2f0d2cc382d8af5e1fda55ed))
+
+- Fixed running `bfs` under Valgrind
+ ([`a01cfac`](https://github.com/tavianator/bfs/commit/a01cfacd423af28af6b7c13ba51e2395f3a52ee7))
+
+- Fixed the exit code when failing to execute a non-existent command with `-exec`/`-ok` on some platforms including OpenBSD and HPPA
+ ([`8c130ca`](https://github.com/tavianator/bfs/commit/8c130ca0117fd225c24569be2ec16c7dc2150a13))
+
+- Fixed `$LS_COLORS` case-sensitivity to match GNU ls more closely when the same extension is specified multiple times
+ ([`08030ae`](https://github.com/tavianator/bfs/commit/08030aea919039165c02805e8c637a9ec1ad0d70))
+
+- Fixed the `-status` bar on Solaris/Illumos
+
+
3.*
===
+3.3.1
+-----
+
+**June 3, 2024**
+
+### Bug fixes
+
+- Reduced the scope of the symbolic link loop change in version 3.3.
+ `-xtype l` remains true for symbolic link loops, matching a change in GNU findutils 4.10.0.
+ However, `-L` will report an error, just like `bfs` prior to 3.3 and other `find` implementations, as required by POSIX.
+
+
+3.3
+---
+
+**May 28, 2024**
+
+### New features
+
+- The `-status` bar can now be toggled by `SIGINFO` (<kbd>Ctrl</kbd>+<kbd>T</kbd>) on systems that support it, and `SIGUSR1` on other systems
+
+- `-regextype` now supports all regex types from GNU find ([#21](https://github.com/tavianator/bfs/issues/21))
+
+- File birth times are now supported on OpenBSD
+
+### Changes
+
+- Symbolic link loops are now treated like other broken links, rather than an error
+
+- `./configure` now expects `--with-libacl`, `--without-libcap`, etc. rather than `--enable-`/`--disable-`
+
+- The ` ` (space) flag is now restricted to numeric `-printf` specifiers
+
+### Bug fixes
+
+- `-regextype emacs` now supports [shy](https://www.gnu.org/software/emacs/manual/html_node/elisp/Regexp-Backslash.html#index-shy-groups) (non-capturing) groups
+
+- Fixed `-status` bar visual corruption when the terminal is resized
+
+- `bfs` now prints a reset escape sequence when terminated by a signal in the middle of colored output ([#138](https://github.com/tavianator/bfs/issues/138))
+
+- `./configure CFLAGS=...` no longer overrides flags from `pkg-config` during configuration
+
+
+3.2
+---
+
+**May 2, 2024**
+
+### New features
+
+- New `-limit N` action that quits immediately after `N` results
+
+- Implemented `-context` (from GNU find) for matching SELinux contexts ([#27](https://github.com/tavianator/bfs/issues/27))
+
+- Implemented `-printf %Z` for printing SELinux contexts
+
+### Changes
+
+- The build system has been rewritten, and there is now a configure step:
+
+ $ ./configure
+ $ make
+
+ See `./configure --help` or [docs/BUILDING.md](/docs/BUILDING.md) for more details.
+
+- Improved platform support
+ - Implemented `-acl` on Solaris/Illumos
+ - Implemented `-xattr` on DragonFly BSD
+
+### Bug fixes
+
+- Fixed some rarely-used code paths that clean up after allocation failures
+
+3.1.3
+-----
+
+**March 6, 2024**
+
+### Bug fixes
+
+- On Linux, the `io_uring` feature probing introduced in `bfs` 3.1.2 only applied to one thread, causing all other threads to avoid using io_uring entirely.
+ The probe results are now copied to all threads correctly.
+ ([`f64f76b`](https://github.com/tavianator/bfs/commit/f64f76b55400b71e8576ed7e4a377eb5ef9576aa))
+
+
+3.1.2
+-----
+
+**February 29, 2024**
+
+### Bug fixes
+
+- On Linux, we now check for supported `io_uring` operations before using them, which should fix `bfs` on 5.X series kernels that support `io_uring` but not all of `openat()`/`close()`/`statx()` ([`8bc72d6`](https://github.com/tavianator/bfs/commit/8bc72d6c20c5e38783c4956c4d9fde9b3ee9140c))
+
+- Fixed a test failure triggered by certain filesystem types for `/tmp` ([#131](https://github.com/tavianator/bfs/issues/131))
+
+- Fixed parsing and interpretation of timezone offsets for explicit reference times used in `-*since` and `-newerXt` ([`a9f3cde`](https://github.com/tavianator/bfs/commit/a9f3cde30426b546ba6e3172e1a7951213a72049))
+
+- Fixed the build on m68k ([`c749c11`](https://github.com/tavianator/bfs/commit/c749c11b04444ca40941dd2ddc5802faed148f6a))
+
+
+3.1.1
+-----
+
+**February 16, 2024**
+
+### Changes
+
+- Performance and scalability improvements
+
+- The file count in `bfs -status` now has a thousands separator
+
+
+3.1
+---
+
+**February 6, 2024**
+
+### New features
+
+- On Linux, `bfs` now uses [io_uring](https://en.wikipedia.org/wiki/Io_uring) for async I/O
+
+- On all platforms, `bfs` can now perform `stat()` calls in parallel, accelerating queries like `-links`, `-newer`, and `-size`, as well as colorized output
+
+- On FreeBSD, `-type w` now works to find whiteouts like the system `find`
+
+### Changes
+
+- Improved `bfs -j2` performance ([`b2ab7a1`](https://github.com/tavianator/bfs/commit/b2ab7a151fca517f4879e76e626ec85ad3de97c7))
+
+- Optimized `-exec` by using `posix_spawn()` when possible, which can avoid the overhead of `fork()` ([`95fbde1`](https://github.com/tavianator/bfs/commit/95fbde17a66377b6fbe7ff1f014301dbbf09270d))
+
+- `-execdir` and `-okdir` are now rejected if `$PATH` contains a relative path, matching the behaviour of GNU find ([`163baf1`](https://github.com/tavianator/bfs/commit/163baf1c9af13be0ce705b133e41e0c3d6427398))
+
+- Leading whitespace is no longer accepted in integer command line arguments like `-links ' 1'` ([`e0d7dc5`](https://github.com/tavianator/bfs/commit/e0d7dc5dfd7bdaa62b6bc18e9c1cce00bbe08577))
+
+### Bug fixes
+
+- `-quit` and `-exit` could be ignored in the iterative deepening modes (`-S {ids,eds}`).
+ This is now fixed ([`670ebd9`](https://github.com/tavianator/bfs/commit/670ebd97fb431e830b1500b2e7e8013b121fb2c5)).
+ The bug was introduced in version 3.0.3 (commit [`5f16169`]).
+
+- Fixed two possible errors in sort mode (`-s`):
+ - Too many open files ([`710c083`](https://github.com/tavianator/bfs/commit/710c083ff02eb1cc5b8daa6778784f3d1cd3c08d))
+ - Out of memory ([`76ffc8d`](https://github.com/tavianator/bfs/commit/76ffc8d30cb1160d55d855d8ac630a2b9075fbcf))
+
+- Fixed handling of FreeBSD union mounts ([`3ac3bee`](https://github.com/tavianator/bfs/commit/3ac3bee7b0d9c9be693415206efa664bf4a7d4a7))
+
+- Fixed `NO_COLOR` handling when it's set to the empty string ([`79aee58`](https://github.com/tavianator/bfs/commit/79aee58a4621d01c4b1e98c332775f3b87213ddb))
+
+- Fixed some portability issues:
+ - [OpenBSD](https://github.com/tavianator/bfs/compare/ee200c07643801c8b53e5b80df704ecbf77a884e...79f1521b0e628be72bed3a648f0ae90b62fc69b8)
+ - [NetBSD](https://github.com/tavianator/bfs/compare/683f2c41c72efcb82ce866e3dcc311ac9bd8b66d...6435684a7d515e18247ae1b3dd9ec8681fee22d0)
+ - [DragonFly BSD](https://github.com/tavianator/bfs/compare/08867473e75e8e20ca76c7fb181204839e28b271...45fb1d952c3b262278a3b22e9c7d60cca19a5407)
+ - [Illumos](https://github.com/tavianator/bfs/compare/4010140cb748cc4f7f57b0a3d514485796c665ce...ae94cdc00136685abe61d55e1e357caaa636d785)
+
+
+3.0.4
+-----
+
+**October 12, 2023**
+
+### Bug fixes
+
+- Fixed a segfault when reporting errors under musl ([`d40eb87`])
+
+[`d40eb87`]: https://github.com/tavianator/bfs/commit/d40eb87cc00f50a5debb8899eacb7fcf1065badf
+
+
+3.0.3
+-----
+
+**October 12, 2023**
+
+### Changes
+
+- Iterative deepening modes (`-S {ids,eds}`) were optimized by delaying teardown until the very end ([`5f16169`])
+
+- Parallel depth-first search (`-S dfs`) was optimized to avoid enqueueing every file separately ([`2572273`])
+
+### Bug fixes
+
+- Iterative deepening modes (`-S {ids,eds}`) were performing iterative *breadth*-first searches since `bfs` 3.0, negating any advantages they may have had over normal breadth-first search.
+ They now do iterative *depth*-first searches as expected.
+ ([`a029d95`])
+
+- Fixed a linked-list corruption that could lead to an infinite loop on macOS and other non-Linux, non-FreeBSD platforms ([`773f4a4`])
+
+[`5f16169`]: https://github.com/tavianator/bfs/commit/5f1616912ba3a7a23ce6bce02df3791b73da38ab
+[`2572273`]: https://github.com/tavianator/bfs/commit/257227326fe60fe70e80433fd34d1ebcb2f9f623
+[`a029d95`]: https://github.com/tavianator/bfs/commit/a029d95b5736a74879f32089514a5a6b63d6efbc
+[`773f4a4`]: https://github.com/tavianator/bfs/commit/773f4a446f03da62d88e6d17be49fdc0a3e38465
+
+
3.0.2
-----
@@ -32,7 +398,7 @@
- Breadth-first search could become highly unbalanced, negating many of the benefits of `bfs`
- - On non-{Linux,FreeBSD} plaforms, directories could stay open longer than necessary, consuming extra memory
+ - On non-{Linux,FreeBSD} platforms, directories could stay open longer than necessary, consuming extra memory
[#107]: https://github.com/tavianator/bfs/pull/107
diff --git a/docs/HACKING.md b/docs/CONTRIBUTING.md
index 0763fda..099157d 100644
--- a/docs/HACKING.md
+++ b/docs/CONTRIBUTING.md
@@ -1,5 +1,5 @@
-Hacking on `bfs`
-================
+Contributing to `bfs`
+=====================
License
-------
diff --git a/docs/RELATED.md b/docs/RELATED.md
new file mode 100644
index 0000000..6e7bd38
--- /dev/null
+++ b/docs/RELATED.md
@@ -0,0 +1,43 @@
+# Related utilities
+
+There are many tools that can be used to find files.
+This is a catalogue of some of the most important/interesting ones.
+
+## `find`-compatible
+
+### System `find` implementations
+
+These `find` implementations are commonly installed as the system `find` utility in UNIX-like operating systems:
+
+- [GNU findutils](https://www.gnu.org/software/findutils/) ([manual](https://www.gnu.org/software/findutils/manual/html_node/find_html/index.html), [source](https://git.savannah.gnu.org/cgit/findutils.git))
+- BSD `find`
+ - FreeBSD `find` ([manual](https://www.freebsd.org/cgi/man.cgi?find(1)), [source](https://cgit.freebsd.org/src/tree/usr.bin/find))
+ - OpenBSD `find` ([manual](https://man.openbsd.org/find.1), [source](https://cvsweb.openbsd.org/src/usr.bin/find/))
+ - NetBSD `find` ([manual](https://man.netbsd.org/find.1), [source](http://cvsweb.netbsd.org/bsdweb.cgi/src/usr.bin/find/))
+- macOS `find` ([manual](https://ss64.com/osx/find.html), [source](https://github.com/apple-oss-distributions/shell_cmds/tree/main/find))
+- Solaris `find`
+ - [Illumos](https://illumos.org/) `find` ([manual](https://illumos.org/man/1/find), [source](https://github.com/illumos/illumos-gate/blob/master/usr/src/cmd/find/find.c))
+
+### Alternative `find` implementations
+
+These are not usually installed as the system `find`, but are designed to be `find`-compatible
+
+- [`bfs`](https://tavianator.com/projects/bfs.html) ([manual](https://man.archlinux.org/man/bfs.1), [source](https://github.com/tavianator/bfs))
+- [schilytools](https://codeberg.org/schilytools/schilytools) `sfind` ([source](https://codeberg.org/schilytools/schilytools/src/branch/master/sfind))
+- [BusyBox](https://busybox.net/) `find` ([manual](https://busybox.net/downloads/BusyBox.html#find), [source](https://git.busybox.net/busybox/tree/findutils/find.c))
+- [ToyBox](https://landley.net/toybox/) `find` ([manual](http://landley.net/toybox/help.html#find), [source](https://github.com/landley/toybox/blob/master/toys/posix/find.c))
+- [Heirloom Project](https://heirloom.sourceforge.net/) `find` ([manual](https://heirloom.sourceforge.net/man/find.1.html), [source](https://github.com/eunuchs/heirloom-project/blob/master/heirloom/heirloom/find/find.c))
+- [uutils](https://uutils.github.io/) `find` ([source](https://github.com/uutils/findutils))
+
+## `find` alternatives
+
+These utilities are not `find`-compatible, but serve a similar purpose:
+
+- [`fd`](https://github.com/sharkdp/fd): A simple, fast and user-friendly alternative to 'find'
+- `locate`
+ - [GNU `locate`](https://www.gnu.org/software/findutils/locate)
+ - [`mlocate`](https://pagure.io/mlocate) ([manual](), [source](https://pagure.io/mlocate/tree/master))
+ - [`plocate`](https://plocate.sesse.net/) ([manual](https://plocate.sesse.net/plocate.1.html), [source](https://git.sesse.net/?p=plocate))
+- [`walk`](https://github.com/google/walk): Plan 9 style utilities to replace find(1)
+- [fselect](https://github.com/jhspetersson/fselect): Find files with SQL-like queries
+- [rawhide](https://github.com/raforg/rawhide): find files using pretty C expressions
diff --git a/docs/SECURITY.md b/docs/SECURITY.md
new file mode 100644
index 0000000..dd3277a
--- /dev/null
+++ b/docs/SECURITY.md
@@ -0,0 +1,126 @@
+Security
+========
+
+Threat model
+------------
+
+`bfs` is a command line program running on multi-user operating systems.
+Those other users may be malicious, but `bfs` should not allow them to do anything they couldn't already do.
+That includes situations where one user (especially `root`) is running `bfs` on files owned or controlled by another user.
+
+On the other hand, `bfs` implicitly trusts the user running it.
+Anyone with enough control over the command line of `bfs` or any `find`-compatible tool can wreak havoc with dangerous actions like `-exec`, `-delete`, etc.
+
+> [!CAUTION]
+> The only untrusted input that should *ever* be passed on the `bfs` command line are **file paths**.
+> It is *always* unsafe to allow *any* other part of the command line to be affected by untrusted input.
+> Use the `-f` flag, or `-files0-from`, to ensure that the input is interpreted as a path.
+
+This still has security implications, including:
+
+- **Information disclosure:** an attacker may learn whether particular files exist by observing `bfs`'s output, exit status, or even side channels like execution time.
+- **Denial of service:** large directory trees or slow/network storage may cause `bfs` to consume excessive system resources.
+
+> [!TIP]
+> When in doubt, do not pass any untrusted input to `bfs`.
+
+
+Executing commands
+------------------
+
+The `-exec` family of actions execute commands, passing the matched paths as arguments.
+File names that begin with a dash may be misinterpreted as options, so `bfs` adds a leading `./` in some instances:
+
+```console
+user@host$ bfs -execdir echo {} \;
+./-rf
+```
+
+This might save you from accidentally running `rm -rf` (for example) when you didn't mean to.
+This mitigation applies to `-execdir`, but not `-exec`, because the full path typically does not begin with a dash.
+But it is possible, so be careful:
+
+```console
+user@host$ bfs -f -rf -exec echo {} \;
+-rf
+```
+
+
+Race conditions
+---------------
+
+Like many programs that interface with the file system, `bfs` can be affected by race conditions&mdash;in particular, "[time-of-check to time-of-use](https://en.wikipedia.org/wiki/Time-of-check_to_time-of-use)" (TOCTTOU) issues.
+For example,
+
+```console
+user@host$ bfs / -user user -exec dangerous_command {} \;
+```
+
+is not guaranteed to only run `dangerous_command` on files you own, because another user may run
+
+```console
+evil@host$ mv /path/to/file /path/to/exile
+evil@host$ mv ~/malicious /path/to/file
+```
+
+in between checking `-user user` and executing the command.
+
+> [!WARNING]
+> Be careful when running `bfs` on directories that other users have write access to, because they can modify the directory tree while `bfs` is running, leading to unpredictable results and possible TOCTTOU issues.
+
+
+Output sanitization
+-------------------
+
+In general, printing arbitrary data to a terminal may have [security](https://hdm.io/writing/termulation.txt) [implications](https://dgl.cx/2023/09/ansi-terminal-security#vulnerabilities-using-known-replies).
+On many platforms, file paths may be completely arbitrary data (except for NUL (`\0`) bytes).
+Therefore, when `bfs` is writing output to a terminal, it will escape non-printable characters:
+
+<pre>
+user@host$ touch $'\e[1mBOLD\e[0m'
+user@host$ bfs
+.
+./$'\e[1mBOLD\e[0m'
+</pre>
+
+However, this is fragile as it only applies when outputting directly to a terminal:
+
+<pre>
+user@host$ bfs | grep BOLD
+<strong>BOLD</strong>
+</pre>
+
+
+Code quality
+------------
+
+Every correctness issue in `bfs` is a potential security issue, because acting on the wrong path may do arbitrarily bad things.
+For example:
+
+```console
+root@host# bfs /etc -name passwd -exec cat {} \;
+```
+
+should print `/etc/passwd` but not `/etc/shadow`.
+`bfs` tries to ensure correct behavior through careful programming practice, an extensive testsuite, and static analysis.
+
+`bfs` is written in C, which is a memory unsafe language.
+Bugs that lead to memory corruption are likely to be exploitable due to the nature of C.
+We use [sanitizers](https://github.com/google/sanitizers) to try to detect these bugs.
+Fuzzing has also been applied in the past, and deploying continuous fuzzing is a work in progress.
+
+
+Supported versions
+------------------
+
+`bfs` comes with [no warranty](/LICENSE), and is maintained by [me](https://tavianator.com/) and [other volunteers](https://github.com/tavianator/bfs/graphs/contributors) in our spare time.
+In that sense, there are no *supported* versions.
+However, as long as I maintain `bfs` I will attempt to address any security issues swiftly.
+In general, security fixes will be part of the latest release, though for significant issues I may backport fixes to older release series.
+
+
+Reporting a vulnerability
+-------------------------
+
+If you think you have found a sensitive security issue in `bfs`, you can [report it privately](https://github.com/tavianator/bfs/security/advisories/new).
+Or you can [report it publicly](https://github.com/tavianator/bfs/issues/new); I won't judge you.
diff --git a/docs/USAGE.md b/docs/USAGE.md
index 86eef87..16aeaf6 100644
--- a/docs/USAGE.md
+++ b/docs/USAGE.md
@@ -7,8 +7,8 @@ When invoked with no arguments, `bfs` will list everything under the current dir
```console
$ bfs
.
-./GNUmakefile
./LICENSE
+./Makefile
./README.md
./completions
./docs
@@ -18,7 +18,7 @@ $ bfs
./completions/bfs.zsh
./docs/BUILDING.md
./docs/CHANGELOG.md
-./docs/HACKING.md
+./docs/CONTRIBUTING.md
./docs/USAGE.md
./docs/bfs.1
...
@@ -53,7 +53,7 @@ $ bfs -name '*.md'
./README.md
./docs/BUILDING.md
./docs/CHANGELOG.md
-./docs/HACKING.md
+./docs/CONTRIBUTING.md
./docs/USAGE.md
```
@@ -64,7 +64,7 @@ When you put multiple expressions next to each other, both of them must match:
```console
$ bfs -name '*.md' -name '*ING*'
./docs/BUILDING.md
-./docs/HACKING.md
+./docs/CONTRIBUTING.md
```
This works because the expressions are implicitly combined with *logical and*.
@@ -84,7 +84,7 @@ $ bfs -name '*.md' -or -name 'bfs.*'
./completions/bfs.zsh
./docs/BUILDING.md
./docs/CHANGELOG.md
-./docs/HACKING.md
+./docs/CONTRIBUTING.md
./docs/USAGE.md
./docs/bfs.1
```
@@ -105,7 +105,7 @@ For expressions like `-name`, that's all they do.
But some expressions, called *actions*, have other side effects.
If no actions are included in the expression, `bfs` adds the `-print` action automatically, which is why the above examples actually print any output.
-The default `-print` is supressed if any actions are given explicitly.
+The default `-print` is suppressed if any actions are given explicitly.
Available actions include printing with alternate formats (`-ls`, `-printf`, etc.), executing commands (`-exec`, `-execdir`, etc.), deleting files (`-delete`), and stopping the search (`-quit`, `-exit`).
@@ -130,6 +130,40 @@ Unlike `-prune`, `-exclude` even works in combination with `-depth`/`-delete`.
---
+### `-limit`
+
+The `-limit N` action makes `bfs` quit once it gets evaluated `N` times.
+Placing it after an action like `-print` limits the number of results that get printed, for example:
+
+```console
+$ bfs -s -type f -name '*.txt'
+./1.txt
+./2.txt
+./3.txt
+./4.txt
+$ bfs -s -type f -name '*.txt' -print -limit 2
+./1.txt
+./2.txt
+```
+
+This is similar to
+
+```console
+$ bfs -s -type f -name '*.txt' | head -n2
+```
+
+but more powerful because you can apply separate limits to different expressions:
+
+```console
+$ bfs \( -name '*.txt' -print -limit 3 -o -name '*.log' -print -limit 4 \) -limit 5
+[At most 3 .txt files, at most 4 .log files, and at most 5 in total]
+```
+
+and more efficient because it will quit immediately.
+When piping to `head`, `bfs` will only quit *after* it tries to output too many results.
+
+---
+
### `-hidden`/`-nohidden`
`-hidden` matches "hidden" files (dotfiles).
diff --git a/docs/bfs.1 b/docs/bfs.1
index 2ecb891..f652106 100644
--- a/docs/bfs.1
+++ b/docs/bfs.1
@@ -1,4 +1,6 @@
-.TH BFS 1
+.\" Copyright © Tavian Barnes <tavianator@tavianator.com>
+.\" SPDX-License-Identifier: 0BSD
+.TH BFS 1 2025-02-26 "bfs 4.0.6"
.SH NAME
bfs \- breadth-first search for your files
.SH SYNOPSIS
@@ -41,17 +43,17 @@ For example,
.PP
.nf
.RS
-.B bfs \\\( \-name '*.txt' \-or \-lname '*.txt' \\\\) \-and \-print
+.B bfs \e( \-name '*.txt' \-or \-lname '*.txt' \e) \-and \-print
.RE
.fi
.PP
-will print the all the paths that are either .txt files or symbolic links to .txt files.
+will print 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
+.B bfs \e( \-name '*.txt' \-or \-lname '*.txt' \e) \-print
.RE
.fi
.PP
@@ -71,7 +73,7 @@ will also accept
.I \-N
or
.IR +N .
-.IR \-N
+.I \-N
means "less than
.IR N ,"
and
@@ -90,7 +92,9 @@ Follow all symbolic links.
Never follow symbolic links (the default).
.TP
.B \-E
-Use extended regular expressions (same as \fB\-regextype \fIposix-extended\fR).
+Use extended regular expressions (same as
+.B \-regextype
+.IR posix-extended ).
.TP
.B \-X
Filter out files with
@@ -109,20 +113,20 @@ The sorting takes place within each directory separately, which makes it differe
but still provides a deterministic ordering.
.TP
.B \-x
-Don't descend into other mount points (same as \fB\-xdev\fR).
+Don't descend into other mount points (same as
+.BR \-xdev ).
.TP
-\fB\-f \fIPATH\fR
+.BI "\-f " PATH
Treat
.I PATH
as a path to search (useful if it begins with a dash).
-.PP
.TP
-\fB\-D \fIFLAG\fR
+.BI "\-D " FLAG
Turn on a debugging flag (see
.B \-D
.IR help ).
.PP
-\fB\-O\fIN\fR
+.BI \-O N
.RS
Enable optimization level
.I N
@@ -178,35 +182,42 @@ Typically far faster than
.IR ids .
.RE
.TP
-\fB\-j\fIN\fR
+.BI \-j N
Search with
.I N
threads in parallel (default: number of CPUs, up to
.IR 8 ).
.SH OPERATORS
.TP
-\fB( \fIexpression \fB)\fR
+.BI "( " expression " )"
Parentheses are used for grouping expressions together.
You'll probably have to write
-.B \\\\(
+.B \e(
.I expression
-.B \\\\)
+.B \e)
to avoid the parentheses being interpreted by the shell.
.PP
\fB! \fIexpression\fR
.br
-\fB\-not \fIexpression\fR
+.B \-not
+.I expression
.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.
+You may have to write \fB\e! \fIexpression\fR to avoid
+.B !
+being interpreted by the shell.
.RE
.PP
-\fIexpression\fR \fIexpression\fR
+.I expression expression
.br
-\fIexpression \fB\-a \fIexpression\fR
+.I expression
+.B \-a
+.I expression
.br
-\fIexpression \fB\-and \fIexpression\fR
+.I expression
+.B \-and
+.I expression
.RS
Short-circuiting "and" operator: if the left-hand
.I expression
@@ -218,9 +229,13 @@ otherwise, returns
.BR false .
.RE
.PP
-\fIexpression \fB\-o \fIexpression\fR
+.I expression
+.B \-o
+.I expression
.br
-\fIexpression \fB\-or \fIexpression\fR
+.I expression
+.B \-or
+.I expression
.RS
Short-circuiting "or" operator: if the left-hand
.I expression
@@ -232,14 +247,14 @@ otherwise, returns
.BR true .
.RE
.TP
-\fIexpression \fB, \fIexpression\fR
+.IB "expression " , " expression"
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
+.BI "\-exclude " expression
Exclude all paths matching the
.I expression
from the search.
@@ -266,7 +281,6 @@ Print usage information, and exit immediately (without parsing the rest of the c
Print version information, and exit immediately.
.RE
.SH OPTIONS
-.PP
.B \-color
.br
.B \-nocolor
@@ -288,8 +302,8 @@ Search in post-order (descendents first).
Follow all symbolic links (same as
.BR \-L ).
.TP
-\fB\-files0\-from \fIFILE\fR
-Treat the NUL ('\\0')-separated paths in
+.BI "\-files0\-from " FILE
+Treat the NUL ('\e0')-separated paths in
.I FILE
as starting points for the search.
Pass
@@ -297,9 +311,9 @@ Pass
.I \-
to read the paths from standard input.
.PP
-\fB\-ignore_readdir_race\fR
+.B \-ignore_readdir_race
.br
-\fB\-noignore_readdir_race\fR
+.B \-noignore_readdir_race
.RS
Whether to report an error if
.B bfs
@@ -307,18 +321,21 @@ detects that the file tree is modified during the search (default:
.BR \-noignore_readdir_race ).
.RE
.PP
-\fB\-maxdepth \fIN\fR
+.B \-maxdepth
+.I N
.br
-\fB\-mindepth \fIN\fR
+.B \-mindepth
+.I N
.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).
+Exclude mount points entirely from the results.
+.TP
+.B \-noerror
+Ignore any errors that occur during traversal.
.TP
.B \-nohidden
Exclude hidden files and directories.
@@ -326,7 +343,7 @@ Exclude hidden files and directories.
.B \-noleaf
Ignored; for compatibility with GNU find.
.TP
-\fB\-regextype \fITYPE\fR
+.BI "\-regextype " TYPE
Use
.IR TYPE -flavored
regular expressions.
@@ -337,7 +354,7 @@ The possible types are
POSIX basic regular expressions (the default).
.TP
.I posix-extended
-POSIX extended resular expressions.
+POSIX extended regular expressions.
.TP
.I ed
Like
@@ -381,6 +398,9 @@ Turn on or off warnings about the command line.
.TP
.B \-xdev
Don't descend into other mount points.
+Unlike
+.BR \-mount ,
+the mount point itself is still included.
.SH TESTS
.TP
.B \-acl
@@ -401,13 +421,17 @@ Find files
minutes ago.
.RE
.PP
-\fB\-anewer \fIFILE\fR
+.B \-anewer
+.I FILE
.br
-\fB\-Bnewer \fIFILE\fR
+.B \-Bnewer
+.I FILE
.br
-\fB\-cnewer \fIFILE\fR
+.B \-cnewer
+.I FILE
.br
-\fB\-mnewer \fIFILE\fR
+.B \-mnewer
+.I FILE
.RS
Find files
.BR a ccessed/ B irthed/ c hanged/ m odified
@@ -416,13 +440,17 @@ more recently than
was modified.
.RE
.PP
-\fB\-asince \fITIME\fR
+.B \-asince
+.I TIME
.br
-\fB\-Bsince \fITIME\fR
+.B \-Bsince
+.I TIME
.br
-\fB\-csince \fITIME\fR
+.B \-csince
+.I TIME
.br
-\fB\-msince \fITIME\fR
+.B \-msince
+.I TIME
.RS
Find files
.BR a ccessed/ B irthed/ c hanged/ m odified
@@ -452,6 +480,10 @@ Find files with POSIX.1e
.BR capabilities (7)
set.
.TP
+.BI "\-context " GLOB
+Find files whose SELinux context matches the
+.IR GLOB .
+.TP
\fB\-depth\fR [\fI\-+\fR]\fIN\fR
Find files with depth
.IR N .
@@ -475,7 +507,11 @@ Find files the current user can execute/read/write.
Always false/true.
.RE
.TP
-\fB\-fstype \fITYPE\fR
+\fB\-flags\fR [\fI\-+\fR]\fIFLAGS\fR
+Find files with matching inode
+.BR FLAGS .
+.TP
+.BI "\-fstype " TYPE
Find files on file systems with the given
.IR TYPE .
.PP
@@ -487,9 +523,11 @@ Find files owned by group/user ID
.IR N .
.RE
.PP
-\fB\-group \fINAME\fR
+.B \-group
+.I NAME
.br
-\fB\-user \fINAME\fR
+.B \-user
+.I NAME
.RS
Find files owned by the group/user
.IR NAME .
@@ -499,15 +537,20 @@ Find files owned by the group/user
Find hidden files (those beginning with
.IR . ).
.PP
-\fB\-ilname \fIGLOB\fR
+.B \-ilname
+.I GLOB
.br
-\fB\-iname \fIGLOB\fR
+.B \-iname
+.I GLOB
.br
-\fB\-ipath \fIGLOB\fR
+.B \-ipath
+.I GLOB
.br
-\fB\-iregex \fIREGEX\fR
+.B \-iregex
+.I REGEX
.br
-\fB\-iwholename \fIGLOB\fR
+.B \-iwholename
+.I GLOB
.RS
Case-insensitive versions of
.BR \-lname / \-name / \-path / \-regex / \-wholename .
@@ -522,19 +565,19 @@ Find files with
.I N
hard links.
.TP
-\fB\-lname \fIGLOB\fR
+.BI "\-lname " GLOB
Find symbolic links whose target matches the
.IR GLOB .
.TP
-\fB\-name \fIGLOB\fR
+.BI "\-name " GLOB
Find files whose name matches the
.IR GLOB .
.TP
-\fB\-newer \fIFILE\fR
+.BI "\-newer " FILE
Find files newer than
.IR FILE .
.TP
-\fB\-newer\fIXY \fIREFERENCE\fR
+.BI \-newer "XY REFERENCE"
Find files whose
.I X
time is newer than the
@@ -570,26 +613,28 @@ as an ISO 8601-style timestamp. For example:
Find files owned by nonexistent groups/users.
.RE
.PP
-\fB\-path \fIGLOB\fR
+.B \-path
+.I GLOB
.br
-\fB\-wholename \fIGLOB\fR
+.B \-wholename
+.I GLOB
.RS
Find files whose entire path matches the
.IR GLOB .
.RE
.TP
-\fB\-perm\fR [\fI\-\fR]\fIMODE\fR
+\fB\-perm\fR [\fI\-+/\fR]\fIMODE\fR
Find files with a matching mode.
.TP
-\fB\-regex \fIREGEX\fR
+.BI "\-regex " REGEX
Find files whose entire path matches the regular expression
.IR REGEX .
.TP
-\fB\-samefile \fIFILE\fR
+.BI "\-samefile " FILE
Find hard links to
.IR FILE .
.TP
-\fB\-since \fITIME\fR
+.BI "\-since " TIME
Find files modified since the ISO 8601-style timestamp
.IR TIME .
See
@@ -668,7 +713,7 @@ days after they were changed.
Find files with extended attributes
.RB ( xattr (7)).
.TP
-\fB\-xattrname\fR \fINAME\fR
+.BI "\-xattrname " NAME
Find files with the extended attribute
.IR NAME .
.TP
@@ -677,28 +722,31 @@ 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).
+Delete any found files (implies
+.BR \-depth ).
.RE
.TP
-\fB\-exec \fIcommand ... {} ;\fR
+.BI "\-exec " "command ... {} ;"
Execute a command.
.TP
-\fB\-exec \fIcommand ... {} +\fR
+.BI "\-exec " "command ... {} +"
Execute a command with multiple files at once.
.TP
-\fB\-ok \fIcommand ... {} ;\fR
+.BI "\-ok " "command ... {} ;"
Prompt the user whether to execute a command.
.PP
-\fB\-execdir \fIcommand ... {} ;\fR
+.B \-execdir
+.I command ... {} ;
.br
-\fB\-execdir \fIcommand ... {} +\fR
+.B \-execdir
+.I command ... {} +
.br
-\fB\-okdir \fIcommand ... {} ;\fR
+.B \-okdir
+.I command ... {} ;
.RS
Like
.BR \-exec / \-ok ,
@@ -710,13 +758,17 @@ Exit immediately with the given status
.RI ( 0
if unspecified).
.PP
-\fB\-fls \fIFILE\fR
+.B \-fls
+.I FILE
.br
-\fB\-fprint \fIFILE\fR
+.B \-fprint
+.I FILE
.br
-\fB\-fprint0 \fIFILE\fR
+.B \-fprint0
+.I FILE
.br
-\fB\-fprintf \fIFILE FORMAT\fR
+.B \-fprintf
+.I FILE FORMAT
.RS
Like
.BR \-ls / \-print / \-print0 / \-printf ,
@@ -725,6 +777,11 @@ but write to
instead of standard output.
.RE
.TP
+.BI "\-limit " N
+Quit once this action is evaluated
+.I N
+times.
+.TP
.B \-ls
List files like
.B ls
@@ -736,12 +793,12 @@ Print the path to the found file.
.B \-print0
Like
.BR \-print ,
-but use the null character ('\\0') as a separator rather than newlines.
+but use the null character ('\e0') as a separator rather than newlines.
Useful in conjunction with
.B xargs
.IR \-0 .
.TP
-\fB\-printf \fIFORMAT\fR
+.BI "\-printf " FORMAT
Print according to a format string (see
.BR find (1)).
These additional format directives are supported:
@@ -887,7 +944,7 @@ is quoted to ensure the glob is processed by
.B bfs
rather than the shell.
.TP
-\fBbfs \-name access_log \-L \fI/var\fR
+.BI "bfs \-name access_log \-L " /var
Finds all files named
.B access_log
under
@@ -896,7 +953,7 @@ following symbolic links.
.B bfs
allows flags and paths to appear anywhere on the command line.
.TP
-\fBbfs \fI~ \fB\-not \-user $USER\fR
+.BI "bfs " ~ " \-not \-user $USER"
Prints all files in your home directory not owned by you.
.TP
.B bfs \-xtype l
@@ -904,7 +961,7 @@ Finds broken symbolic links.
.TP
.B bfs \-name config \-exclude \-name .git
Finds all files named
-.BR config,
+.BR config ,
skipping every
.B .git
directory.