bfs

**[Features]   •   [Installation]   •   [Usage]   •   [Building]   •   [Contributing]   •   [Changelog]**

[Features]: #features
[Installation]: #installation
[Usage]: /docs/USAGE.md
[Building]: /docs/BUILDING.md
[Contributing]: /docs/CONTRIBUTING.md
[Changelog]: /docs/CHANGELOG.md

  Screencast

`bfs` is a variant of the UNIX `find` command that operates [**breadth-first**](https://en.wikipedia.org/wiki/Breadth-first_search) rather than [**depth-first**](https://en.wikipedia.org/wiki/Depth-first_search).
It is otherwise compatible with many versions of `find`, including

**[POSIX]   •   [GNU]   •   [FreeBSD]   •   [OpenBSD]   •   [NetBSD]   •   [macOS]**

[POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/utilities/find.html
[GNU]: https://www.gnu.org/software/findutils/
[FreeBSD]: https://www.freebsd.org/cgi/man.cgi?find(1)
[OpenBSD]: https://man.openbsd.org/find.1
[NetBSD]: https://man.netbsd.org/find.1
[macOS]: https://ss64.com/osx/find.html

If you're not familiar with `find`, the [GNU find manual](https://www.gnu.org/software/findutils/manual/html_mono/find.html) provides a good introduction.

Features
--------

bfs operates breadth-first, which typically finds the file(s) you're looking for faster.

Imagine the following directory tree:

haystack
├── deep
│   └── 1
│       └── 2
│           └── 3
│               └── 4
│                   └── ...
└── shallow
    └── needle

`find` will explore the entire `deep` directory tree before it ever gets to the `shallow` one that contains what you're looking for.
On the other hand, `bfs` lists files from shallowest to deepest, so you never have to wait for it to explore an entire unrelated subtree.

 bfs find

```console
$ bfs haystack
haystack
haystack/deep
haystack/shallow
haystack/deep/1
haystack/shallow/needle
...
```


```console
$ find haystack
haystack
haystack/deep
haystack/deep/1
haystack/deep/1/2
haystack/deep/1/2/3
haystack/deep/1/2/3/4
...
haystack/shallow
haystack/shallow/needle
```


bfs tries to be easier to use than find, while remaining compatible.

For example, `bfs` is less picky about where you put its arguments:

 bfs find

```console
$ bfs -L -name 'needle' haystack
haystack/needle

$ bfs haystack -L -name 'needle'
haystack/needle

$ bfs -L haystack -name 'needle'
haystack/needle
```


```console
$ find -L -name 'needle' haystack
find: paths must precede expression: haystack

$ find haystack -L -name 'needle'
find: unknown predicate `-L'

$ find -L haystack -name 'needle'
haystack/needle
```


bfs gives helpful errors and warnings.

For example, `bfs` will detect and suggest corrections for typos:

```console
$ bfs -nam needle
bfs: error: bfs -nam needle
bfs: error:     ~~~~
bfs: error: Unknown argument; did you mean -name?
```

`bfs` also includes a powerful static analysis to help catch mistakes:

```console
$ bfs -print -name 'needle'
bfs: warning: bfs -print -name needle
bfs: warning:            ~~~~~~~~~~~~
bfs: warning: The result of this expression is ignored.
```


bfs adds some options that make common tasks easier.

For example, the `-exclude` operator skips over entire subtrees whenever an expression matches.
`-exclude` is both more powerful and easier to use than the standard `-prune` action; compare

$ bfs -name config -exclude -name .git

to the equivalent

$ find ! \( -name .git -prune \) -name config

As an additional shorthand, `-nohidden` skips over all hidden files and directories.
See the [usage documentation](/docs/USAGE.md#extensions) for more about the extensions provided by `bfs`.

Installation
------------

bfs may already be packaged for your operating system.

 Linux macOS

Alpine Linux (https://pkgs.alpinelinux.org/packages?name=bfs)
# apk add bfs

Arch Linux (https://archlinux.org/packages/extra/x86_64/bfs/)
# pacman -S bfs

Debian (https://packages.debian.org/sid/bfs)/Ubuntu (https://packages.ubuntu.com/kinetic/bfs)
# apt install bfs

Fedora Linux (https://src.fedoraproject.org/rpms/bfs)
# dnf install bfs

Gentoo (https://packages.gentoo.org/packages/sys-apps/bfs)
# emerge sys-apps/bfs

GNU Guix (https://packages.guix.gnu.org/packages/bfs/)
# guix install bfs

NixOS (https://search.nixos.org/packages?channel=unstable&show=bfs&from=0&size=1&sort=relevance&type=packages&query=bfs)
# nix-env -i bfs

Void Linux (https://voidlinux.org/packages/?arch=x86_64&q=bfs)
# xbps-install -S bfs

Homebrew (https://formulae.brew.sh/formula/bfs)
$ brew install bfs

MacPorts (https://ports.macports.org/port/bfs/)
# port install bfs

 BSD

FreeBSD (https://www.freshports.org/sysutils/bfs)
# pkg install bfs

OpenBSD (https://openports.pl/path/sysutils/bfs)
# pkg_add bfs

To build bfs from source, you may need to install some dependencies.

The only absolute requirements for building `bfs` are a C compiler, [GNU make](https://www.gnu.org/software/make/), and [Bash](https://www.gnu.org/software/bash/).
These are installed by default on many systems, and easy to install on most others.
Refer to your operating system's documentation on building software.

`bfs` also depends on some system libraries for some of its features.
Here's how to install them on some common platforms:

Alpine Linux
# apk add acl{,-dev} attr libcap{,-dev} liburing-dev oniguruma-dev

Arch Linux
# pacman -S acl attr libcap liburing oniguruma

Debian/Ubuntu
# apt install acl libacl1-dev attr libattr1-dev libcap2-bin libcap-dev liburing-dev libonig-dev

Fedora
# dnf install acl libacl-devel attr libcap-devel liburing-devel oniguruma-devel

NixOS
# nix-env -i acl attr libcap liburing oniguruma

Void Linux
# xbps-install -S acl-{devel,progs} attr-progs libcap-{devel,progs} liburing-devel oniguruma-devel

Homebrew
$ brew install oniguruma

MacPorts
# port install oniguruma6

FreeBSD
# pkg install oniguruma

These dependencies are technically optional, though strongly recommended.
See the [build documentation](/docs/BUILDING.md#dependencies) for how to disable them.

Once you have the dependencies, you can build bfs.

Download one of the [releases](https://github.com/tavianator/bfs/releases) or clone the [git repo](https://github.com/tavianator/bfs).
Then run

    $ ./configure
    $ make

This will build the `./bin/bfs` binary.
Run the test suite to make sure it works correctly:

    $ make check

If you're interested in speed, you may want to build the release version instead:

    $ ./configure --enable-release
    $ make

Finally, if you want to install it globally, run

    # make install


