Command-Line Search: fd vs bfs
Parallel & BFS Verified 2026
fd GitHub Stars
44.2k+
200+ contributors • Rust
bfs GitHub Stars
1.3k+
Tavian Barnes • Pure C
Early Exit Speedup
Up to 430×
bfs shallow target search vs find
POSIX Compatibility
100% Drop-In
alias find=bfs preserves all scripts

Traversal Architecture & Design Philosophy

DFS vs BFS

While both tools blow standard single-threaded GNU find out of the water, they are optimized for diametrically opposite traversal philosophies:

⚡ fd — Parallel Depth-First Search Rust

Built on Rust's ignore::WalkParallel engine. Uses a multi-threaded work-stealing deque where worker threads dive down independent directory subtrees.

  • Stack-Bounded Memory: Memory footprint is strictly $O(\text{threads} \times \text{depth})$ (~5–20 MB).
  • Developer Defaults: Automatically excludes .gitignore, .git/, and hidden files.
  • SIMD Regex: Blazing-fast pattern filtering across massive warm-cache repositories.
🌊 bfs — Asynchronous Breadth-First Search Pure C

Custom Asynchronous I/O Queue (ioq.c) with lock-free MPMC ring buffers and a priority file descriptor cache (dircache.c).

  • Instant Shallow Discovery: Inspects depth $k$ entirely before descending to depth $k+1$.
  • 100% POSIX/GNU/BSD Parity: Drop-in replacement for all standard find scripts and expressions.
  • openat() Cache: Avoids redundant path lookups and gracefully evicts FDs to prevent EMFILE.

Performance Benchmarks

Empirical Data (7.6M Files Dataset)

Relative Speedup vs GNU find (Higher is Better)

Memory Consumption (MB, Lower is Better)

Workload Scenario GNU find fd (Parallel DFS) bfs (Breadth-First) Winner & Why
Shallow Target Discovery (-quit / head) 1.0× (Baseline) ~8.5× Up to 430× bfs — BFS visits top-level entries before descending into massive directories.
Full Tree Traversal (Warm Cache) 1.0× 2.75× 2.95× bfs / fd — Both saturate hardware threads; bfs leads slightly via dircache.
Regex Pattern Matching (Warm Cache) 1.0× 10× – 23× 3.5× – 6× fd — Rust's SIMD-accelerated regex engine and auto-pruned `.git` tree.
Cold Cache Traversal (Disk I/O Bound) 1.0× 4.5× – 7.2× 5.1× – 8.0× Tie (bfs & fd) — Multi-threading saturates NVMe queue depths over single-threaded find.

Syntax & Feature Comparison

Side-by-Side
Feature / Task Traditional find bfs Syntax fd Syntax
Find by File Extension find . -name "*.js" bfs -name "*.js" fd -e js
Case-Insensitive Search find . -iname "*readme*" bfs -iname "*readme*" fd readme (Smart-case default)
Ignore .git & Build Folders find . -name .git -prune -o -print bfs -exclude -name .git fd (Automatic default)
Skip Hidden Files find . -name ".*" -prune -o -print bfs -nohidden fd (Automatic default)
Time-Based Filter find . -mtime -7 bfs -mtime -7 fd --changed-within 7d
Size Range Filter find . -size +100M -size -1G bfs -size +100M -size -1G fd -S +100M -S -1G
Parallel Batch Execution Requires xargs -P bfs -j8 -exec cmd {} \; fd -x cmd {} or fd -X cmd
Prevent Symlink Loops Complex manual check bfs -L -unique fd -L
Rich Path Placeholders {} only {} only {}, {/} (name), {//} (dir), {.} (no ext)

Pros & Cons Matrix

Trade-Off Analysis
fd (sharkdp/fd) Rust • 44.2k ★
PROS
  • Ultra-concise, intuitive syntax (fd search_term).
  • Smart defaults: ignores .gitignore, .ignore, hidden files, and binary files automatically.
  • Smart-case sensitivity (lowercase = insensitive; uppercase = sensitive).
  • Rich replacement tokens for execution ({/}, {//, {.}, {/.}).
  • Full native cross-platform support (Linux, macOS, Windows Scoop/Winget).
  • Massive ecosystem adoption (default in fzf, Telescope, Projectile).
CONS
  • Incompatible with standard POSIX find syntax and shell scripts.
  • Default filtering can accidentally hide files in administrative/system contexts unless -u/-H is passed.
  • Non-deterministic output stream order across parallel worker runs.
bfs (tavianator/bfs) Pure C • 1.3k ★
PROS
  • 100% drop-in replacement for POSIX, GNU, and BSD find (alias find=bfs).
  • Breadth-First order finds shallow targets up to 430× faster on early exits.
  • Advanced extensions: -exclude, -nohidden, -unique (breaks symlink cycles).
  • Sophisticated C architecture: ioq MPMC queue + dircache openat() LRU.
  • Ultra-permissive 0BSD license (public domain equivalent).
  • Packaged in virtually all Linux/BSD repositories and Homebrew.
CONS
  • Requires traditional verbose POSIX predicate expressions (-name, -type).
  • Does not automatically parse .gitignore files.
  • No native Windows binary support (strictly UNIX/POSIX-centric).

Which One Should You Use?

Decision Guide
Choose fd if you want:

Everyday interactive terminal navigation, searching inside Git repositories and codebases without seeing node_modules or target/ junk, interactive fuzzy-finding via fzf, or working on native Windows workstations.

Choose bfs if you want:

A transparent 100% speedup for all existing shell scripts and sysadmin tasks via alias find=bfs, searching whole root filesystems (/), finding top-level files instantly with early exits, or maintaining strict POSIX/GNU compatibility.

Authoritative Citations & References