Modern Replacements for find
Replace find with fd, bfs or fselect: regex search with smart defaults, a breadth-first drop-in, or SQL-like file queries.
Updated
short verdict
Pick fd for everyday interactive searches: `fd PATTERN` replaces `find -iname '*PATTERN*'` and skips hidden and gitignored files. Pick bfs if you have existing scripts and want find's predicates unchanged. Pick fselect when you need to filter on metadata such as EXIF, MP3 tags or hashes, or aggregate results.
find matches files by name and attributes, but its expression syntax is verbose and it walks directories depth-first with no awareness of ignore files. The three tools here take different routes: fd shortens the syntax and changes the defaults, bfs keeps find's syntax and changes traversal order and error handling, and fselect replaces the expression language with SQL-like queries.
this page is for
- Developers who search project trees and want ignore files respected
- Admins with find scripts who want a compatible binary
- Anyone querying files by size, dates, tags or hashes
A find replacement with regex patterns, smart case and .gitignore support, so a plain `fd PATTERN` covers most name searches.
best for
- Interactive searches in code repositories
- Running a command on every match with -x or -X
strengths
- `fd PATTERN` replaces `find -iname '*PATTERN*'`
- Parallelized directory traversal
- Smart case: case-insensitive until the pattern has an uppercase letter
- `-x` runs a command per result in parallel, `-X` batches; placeholders include `{}`, `{.}` and `{/}`
weaknesses
- Hides dotfiles and gitignored paths by default; you need `-H` and `-I` to match find's output
- Patterns are regex by default; exact filename globs need `-g`
- Uses its own syntax rather than find's predicates, so existing find scripts need rewriting
A breadth-first reimplementation of find that stays compatible with POSIX, GNU and BSD find, so existing expressions keep working.
best for
- Scripts and habits built on find predicates
- Searching large trees where matches sit near the top
strengths
- Supports the same predicates, actions and expressions as standard find
- Breadth-first traversal reaches shallow matches before descending into deep subtrees
- Typo correction suggestions and static analysis warnings for suspect expressions
- Extensions `-exclude` for skipping subtrees and `-nohidden` for ignoring hidden files
weaknesses
- Keeps find's long expression syntax for simple name searches
- Regex matching by default, smart case and .gitignore handling are not documented by the project
- Packaging is documented for Homebrew, APT and DNF only
Queries the filesystem with SQL-like statements, which suits metadata-heavy searches that are awkward to express in find.
best for
- Filtering by image dimensions, EXIF, MP3 tags, MIME type or hashes
- Reports with COUNT, SUM, AVG, MIN or MAX over results
strengths
- Queries like `fselect size, path from /home/user where name = '*.cfg' or name = '*.tmp'`
- Searches inside archives and reads image, MP3, hash, MIME and POSIX attribute data
- Outputs CSV, JSON or HTML, and has an interactive mode for building queries
- Date filters accept 'today', 'yesterday' and 'last fri'; can respect .gitignore, .hgignore and .dockerignore
weaknesses
- The SQL-like syntax shares nothing with find, so no script or muscle memory carries over
- A simple name lookup takes more typing than `fd PATTERN` or `find -name`
- No find-compatible flags are documented
What changes compared to find
The tools differ from find in syntax, defaults and output, not just speed.
- fd: `fd PATTERN` replaces `find -iname '*PATTERN*'`, with regex matching and `-g` for globs
- fd: hidden files and .gitignore matches are skipped unless you pass `-H` or `-I`
- fd: output is colored by file type, and `-x`/`-X` replace find's `-exec` with parallel or batched runs
- bfs: walks breadth-first instead of depth-first, so shallow matches appear sooner
- bfs: accepts arguments in flexible order and suggests corrections for typos
- fselect: you write `select ... from ... where ...` queries and can emit CSV, JSON or HTML
Switching from find
Migration effort depends on the tool.
- bfs: documented as compatible with POSIX, GNU and BSD find and as a drop-in for existing scripts
- bfs: add `-exclude` or `-nohidden` where you used long `-prune` style expressions
- fd: swap `find -iname '*foo*'` for `fd foo`; replace `-exec` with `-x`, or `-X` for one batched call
- fselect: rewrite each search as a query; no flag mapping from find is documented
When not to use these
- You need a binary that is guaranteed to exist on every minimal server or container; find ships with the system, these do not
- Your script relies on find's exact output, including hidden and ignored files, and you cannot retest it
FAQ
- Is fd a drop-in replacement for find in scripts?
- No. fd uses its own syntax (`fd PATTERN`, `-x`, `-X`) and skips hidden and gitignored files by default. Compatibility with find's flags is not documented, so existing scripts need rewriting.
- Which tool can run existing find scripts unchanged?
- bfs. The project describes it as compatible with POSIX, GNU and BSD find, supporting the same predicates, actions and expressions, and as a drop-in replacement for existing scripts.
- Does any of these respect .gitignore?
- fd does automatically, and `-I` turns that off. fselect can respect .gitignore, .hgignore and .dockerignore. bfs does not document gitignore support, but `-nohidden` skips hidden files.
- Which one is best for searching by file metadata?
- fselect. It can filter on image width, height and EXIF, MP3 genre, bitrate and year, file hashes, MIME types and POSIX attributes, and it can aggregate with COUNT, SUM, AVG, MIN and MAX.