C Shell Roff Makefile
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
tests tests: Add tests for mode 000 Jul 20, 2018
.gitattributes Add a .travis.yml Dec 9, 2016
.gitignore Ignore .d files. Jun 20, 2015
.travis.yml travis: Do 32-bit builds too Dec 22, 2016
COPYING Re-license under the BSD Zero Clause License Jul 27, 2017
Makefile Release 1.2.3 Jul 15, 2018
README.md README: Add a repology badge Apr 6, 2018
RELEASES.md Release 1.2.3 Jul 15, 2018
bfs.1 printf: Add %w and %Wk for file birth times Jan 20, 2018
bfs.h Release 1.2.3 Jul 15, 2018
bftw.c bftw: Use bftw_action as the return type when applicable Jun 25, 2018
bftw.h stat: New wrapper around the stat() family Jan 9, 2018
cmdline.h Minor header cleanups Jan 9, 2018
color.c stat: New wrapper around the stat() family Jan 9, 2018
color.h color: Implement %m for cfprintf() Nov 13, 2017
dstring.c Re-license under the BSD Zero Clause License Jul 27, 2017
dstring.h Re-license under the BSD Zero Clause License Jul 27, 2017
eval.c stat: Don't assume blocks are 512 bytes Jul 24, 2018
eval.h Minor header cleanups Jan 9, 2018
exec.c exec: Add some debugging info about failed commands Jul 8, 2018
exec.h exec: Don't allow anything between {} and + Jul 29, 2017
expr.h stat: New wrapper around the stat() family Jan 9, 2018
main.c Report errors that occur when closing files Oct 21, 2017
mtab.c mtab: Fall back on /proc/mounts if /etc/mtab isn't available Mar 4, 2018
mtab.h stat: New wrapper around the stat() family Jan 9, 2018
opt.c Keep track of required FDs per-expr Dec 15, 2017
parse.c parse: Add some missing failure messages Jul 7, 2018
printf.c printf: Support all standard strftime() directives Jul 24, 2018
printf.h stat: New wrapper around the stat() family Jan 9, 2018
stat.c stat: Support the glibc statx() wrapper Jul 11, 2018
stat.h stat: Don't assume blocks are 512 bytes Jul 24, 2018
tests.sh printf: Support %B, GNU find's undocumented birth time specifier Jul 24, 2018
typo.c Re-license under the BSD Zero Clause License Jul 27, 2017
typo.h Re-license under the BSD Zero Clause License Jul 27, 2017
util.c util: Preserve errno in pipe_cloexec() Jul 25, 2018
util.h stat: New wrapper around the stat() family Jan 9, 2018

README.md

bfs

License LOC Build Status

Breadth-first search for your files.

bfs is a variant of the UNIX find command that operates breadth-first rather than depth-first. It is otherwise intended to be compatible with many versions of find, including

If you're not familiar with find, the GNU find manual provides a good introduction.

Breadth vs. depth

The advantage of breadth-first over depth first search is that it usually 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.

$ 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

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 haystack
haystack
haystack/deep
haystack/shallow
haystack/deep/1
haystack/shallow/needle
haystack/deep/1/2
haystack/deep/1/2/3
haystack/deep/1/2/3/4
...

Easy

bfs tries to be easier to use than find, while remaining compatible. For example, bfs is less picky about where you put its arguments:

$ find -L -name 'needle' haystack
find: paths must precede expression: haystack
$ bfs -L -name 'needle' haystack
haystack/needle

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

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

bfs also adds some extra options that make some common tasks easier. Compare bfs -nohidden to

find -name '.?*' -prune -o -print

Pretty

When bfs detects that its output is a terminal, it automatically colors its output with the same colors ls uses. This makes it easier to identify relevant files at a glance.

Screenshot

Try it!

To get bfs, download one of the releases or clone the git repo. Then run

$ make

This will build the bfs binary in the current directory. You can test it out:

$ ./bfs -nohidden

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

$ make clean
$ make release

Finally, if you want to install it globally, run

$ sudo make install

Alternatively, bfs may already be packaged for your distribution of choice:

Packaging status

For example:

# apt install bfs                  # Debian/Ubuntu
# brew install tavianator/tap/bfs  # macOS Homebrew