LinuxCommandLibrary

bfs

Breadth-first search files in a directory tree

TLDR

Find files by extension

$ bfs [root_path] -name '[*.ext]'
copy

Find files matching multiple path/name patterns
$ bfs [root_path] -path '[**/path/**/*.ext]' -or -name '[*pattern*]'
copy

Find directories matching a given name, in case-insensitive mode
$ bfs [root_path] -type d -iname '[*lib*]'
copy

Find files matching a given pattern, excluding specific paths
$ bfs [root_path] -name '[*.py]' -not -path '[*/site-packages/*]'
copy

Find files matching a given size range, limiting the recursive depth to "1"
$ bfs [root_path] -maxdepth 1 -size [+500k] -size [-10M]
copy

Run a command for each file (use {} within the command to access the filename)
$ bfs [root_path] -name '[*.ext]' -exec [wc -l] {} \;
copy

Find all files modified today and pass the results to a single command as arguments
$ bfs [root_path] -daystart -mtime [-1] -exec [tar -cvf archive.tar] {} \+
copy

Find empty files (0 byte) or directories and delete them verbosely
$ bfs [root_path] -type [f|d] -empty -delete -print
copy

SYNOPSIS

bfs [-H|-L|-P] [-D debuglevel] [-O level] [-t type_list] [path...] [expression]

PARAMETERS

-H
    Follow symlinks on command line.

-L
    Follow all symlinks (default).

-P
    Never follow symlinks.

-D debugopts
    Debug output; opts like tree,stat,time,exec,rate,xattr.

-O level
    Optimization level: 0=none, 1=default, 2=aggressive, 3=all.

-t type[,type...]
    Traverse only specified file types (e.g., f,d for files,dirs).

-xdev, -mount
    Don't cross filesystem boundaries.

-maxdepth N
    Descend at most N levels.

-mindepth N
    Don't act on first N levels.

-name PATTERN
    Basename matches shell pattern.

-type TYPE
    File type: f=file, d=dir, l=symlink, etc.

-print
    Print matching paths (default action).

-exec cmd {} ;
    Execute cmd on matches; {} expands to path.

-execdir cmd {} ;
    Like -exec but chdir to dir first.

-delete
    Delete matching files/dirs.

-print0
    Print paths NUL-terminated.

DESCRIPTION

bfs is a high-performance reimplementation of the classic Unix find utility that uses breadth-first search (BFS) instead of depth-first traversal. This means it processes all files and directories at a given depth level before moving deeper, which can dramatically improve speed for workloads targeting shallow files, such as build systems, backups, or searches in large trees with many levels.

Designed as a drop-in replacement for GNU find(1), bfs supports nearly identical syntax, including all standard predicates (-name, -type, -mtime, etc.), actions (-print, -exec, -delete), and options (-maxdepth, -mindepth, -xdev). It adds enhancements like more efficient -execdir and -okdir, better symlink handling, mountpoint detection, and optimizations reducing memory use and I/O.

Key benefits include up to 10x faster execution on benchmarks (e.g., Linux kernel tree), predictable ordering for reproducible results, and support for sparse filesystems. It's particularly useful in CI/CD, package managers, and scripting where traversal order impacts performance.

bfs is portable (Linux, macOS, BSD, Windows via WSL), written in C99, and licensed under MIT. Install via package managers; source builds easily.

CAVEATS

Not installed by default; requires bfs package. Minor syntax differences from GNU find (e.g., stricter quoting). High optimization (-O3) may increase CPU use. Not suitable for very deep trees where DFS excels.

INSTALLATION

Debian/Ubuntu: sudo apt install bfs
Fedora: sudo dnf install bfs
macOS: brew install bfs
Arch: pacman -S bfs.

EXAMPLE USAGE

bfs -name '*.o' -delete
bfs src -type f -name '*.c' -exec gcc -MM {} +
bfs / -maxdepth 2 -type d -fstype 'nfs|tmpfs'.

PERFORMANCE TIP

Use -O2 or -O3 for large trees; combine with -t f,d to skip special files.

HISTORY

Created by Tavian Barnes in 2018 to address find's depth-first inefficiencies. Inspired by BFS algorithms; benchmarks showed 2-10x speedups. Actively maintained, v3.0+ adds Windows support, fts(3) backend. Widely adopted in Nixpkgs, Gentoo, and dev tools.

SEE ALSO

find(1), locate(1), xargs(1), updatedb(8)

Copied to clipboard