How to Install and Use bfs on Linux as a Fast Breadth-First Alternative to find

The standard Unix find utility is one of the most versatile command-line tools in system administration. However, find traverses directory trees strictly using a depth-first search (DFS) algorithm. When searching large file trees, monorepos, or nested network file systems, depth-first traversal dives deeply into the bottom of the first subdirectory branch before surfacing—often spending minutes exploring massive node_modules or build directories while the target file sits right in the top-level directory.

To overcome this architectural limitation, developer Tavian Barnes created bfs (Breadth-First Search). Built as a 100% flag-compatible alternative to GNU find, bfs visits shallow directories first, finding target files near the root orders of magnitude faster. Furthermore, bfs features colored terminal output, interactive error handling, and parallel directory iteration. This comprehensive tutorial walks you through installing bfs on Linux, understanding breadth-first traversal mechanics, and utilizing advanced search expressions.


Breadth-First (bfs) vs Depth-First (find): The Difference

To understand why bfs frequently outperforms standard find in interactive workflows, consider how directory trees are traversed:

  • Depth-First Search (Standard find): Traverses down to the deepest leaf node of directory A/B/C/D/ before examining directory E/. If you are searching for a configuration file located in ~/project/config.yaml, standard find may first crawl hundreds of thousands of files inside deep caches, cache directories, or vendor trees.
  • Breadth-First Search (bfs): Traverses level-by-level. It inspects all files at depth 1, then all files at depth 2, and so forth. In typical interactive use, users are far more likely to search for files closer to their working directory root, allowing bfs to display matches almost instantaneously.

Step 1: Installing bfs on Linux

bfs is packaged natively across modern Linux distribution repositories and can also be installed as a precompiled standalone binary.

Method A: On Ubuntu and Debian Systems

Available natively in Debian 11/12 and Ubuntu 22.04 LTS or newer:

sudo apt update
sudo apt install -y bfs

Method B: On Fedora, RHEL, and CentOS Stream

Available in Fedora repositories and EPEL for Enterprise Linux:

sudo dnf install -y bfs

Method C: On Arch Linux

sudo pacman -S bfs

Method D: Building from Source (Latest Version)

If your distribution repository contains an older release, compiling bfs requires only a standard C compiler and make:

# Install build dependencies
sudo apt install -y git gcc make libonig-dev libcap-dev libacl1-dev

# Clone repository and compile
git clone https://github.com/tavianator/bfs.git
cd bfs
./configure
make -j$(nproc)
sudo make install

# Confirm installation
bfs --version

Step 2: Basic Syntax and Drop-In Compatibility with find

Because bfs mirrors GNU find flag syntax, any standard find command can be executed with bfs without modification:

# Standard file search by name
bfs . -name "*.conf"

# Case-insensitive name search
bfs /etc -iname "*nginx*"

# Search by file type (files only)
bfs ~/projects -type f -name "Dockerfile"

# Search by file type (directories only)
bfs ~ -type d -name ".git"

Unlike standard find, bfs automatically colorizes output based on your system’s LS_COLORS configuration, rendering executables, symlinks, archives, and directories in distinct hues for fast visual scanning.


Step 3: Shallow File Discovery with Early Exit

When searching for a single file or inspecting whether a file exists in a project, combining breadth-first traversal with the -exit action returns results with near-zero latency:

# Find the nearest .env file and stop immediately
bfs . -name ".env" -print -exit

While GNU find . -name ".env" -print -quit would still dive down into the deepest subdirectory branch first if it encountered a folder before the .env file, bfs checks the top level immediately and terminates instantly upon matching.


Step 4: Advanced Filtering Expressions in bfs

bfs supports the full spectrum of time, size, and permission predicates supported by modern Unix linkers and shells:

1. Searching by File Size

# Find all files larger than 100 Megabytes
bfs /var/log -type f -size +100M

# Find empty files or directories
bfs . -empty

2. Filtering by Modification and Access Times

# Files modified within the last 24 hours
bfs ~/documents -type f -mtime -1

# Files modified more than 30 days ago
bfs /tmp -type f -mtime +30

3. Filtering by Unix Permissions

# Find world-writable files (security audit)
bfs /var/www -type f -perm -o+w

# Find files with SUID bit set
bfs /usr/bin -type f -perm -4000

Step 5: Excluding Heavy Directories with -exclude

In standard find, pruning deep directories requires unwieldy syntax: -name node_modules -prune -o -print. bfs introduces an intuitive, human-friendly -exclude action that operates seamlessly:

# Search for TypeScript files, skipping node_modules and .git completely
bfs . -exclude -name node_modules -exclude -name .git -name "*.ts"

When bfs encounters an excluded directory name, it prunes the entire subtree without descending into it, conserving disk read cycles and CPU memory.


Step 6: Executing Batch Actions with -exec

Like find, bfs can pass matching paths directly to background commands or utilities:

# Compute SHA256 checksums for all ISO images
bfs /data/iso -name "*.iso" -exec sha256sum {} +

# Change file permissions on all shell scripts
bfs ~/scripts -name "*.sh" -exec chmod +x {} +

Using + at the end of the -exec expression aggregates multiple file paths into a single command invocation, avoiding the overhead of spawning a new subshell process for every single file.


Parallel Breadth-First Search (-j)

On modern multi-core systems with high-speed NVMe solid-state storage, bfs can parallelise directory traversal across multiple CPU threads using the -j flag:

# Run breadth-first search across all available CPU cores
bfs / -j$(nproc) -name "nginx.conf" 2>/dev/null

Multi-threaded traversal dramatically accelerates searches across massive filesystems containing millions of inodes.


bfs vs find Feature Comparison Table

Feature GNU find bfs
Traversal Algorithm Depth-First Search (DFS) Breadth-First Search (BFS)
Shallow File Speed Slow (dives into deep branches first) Fast (evaluates shallow levels first)
Colored Terminal Output No (plain text only) Yes (automatic LS_COLORS support)
Multi-Core Parallelism No (single-threaded) Yes (via -j <threads>)
Pruning Syntax Complex (-prune -o ...) Intuitive (-exclude -name ...)
Flag Compatibility POSIX / GNU Standard 100% GNU find Compatible

Troubleshooting Common bfs Queries

Issue Cause Fix
“Permission denied” clutter Attempting to read root/system files Redirect stderr: bfs / -name "app.log" 2>/dev/null
Unexpected shell expansion error Unquoted wildcard (e.g., bfs . -name *.txt) Always wrap wildcards in single or double quotes: bfs . -name "*.txt"
Out of memory on multi-billion inode trees Queueing massive breadth layers Limit maximum search depth using -maxdepth <N> (e.g., bfs . -maxdepth 5).

Get the best tech tips delivered straight to your inbox.

Join thousands of readers mastering Apple, Google, Microsoft, and Linux.