Skip to content



efind (extendable find) searches for files in a directory hierarchy.

Basically it's a wrapper for GNU find providing an easier and more intuitive expression syntax. It can be extended by custom functions to filter search results. Furthermore, it has built-in sort and range functionality.

Watch this screencast to get a brief overview:


Running efind without any argument the search expression is read from standard input (stdin) and files are searched in the user's home directory. A different directory and expression can be specified with the --dir and --expr options:

$ efind --dir=/tmp --expr="size>1M and type=file"

efind tries to handle the first arguments as path(s) and expression. It's valid to run efind the following way:

$ efind ~/git ~/code "type=file and name='CHANGELOG'"

efind is shipped with a manpage, of course.

$ man efind


Print five largest files.

efind . "type=file" \
        --order-by "-{bytes}" \
        --printf "%-10{kb} | %{path}\n" \
        --limit 5

Find first text document containing a string and stop immediately.

efind . "name='*.txt' and text_contains('find me')" --limit 1

Filter audio files by artist and convert them to WAV:

efind ~/Music \
      "extension_in('.mp3, .ogg') and artist_matches('David Bowie')" \
      --exec sox "%{filename}" tmp/"%{name}.wav" \;

Expression Syntax

A search expression consists of at least one comparison or file flag to test. Multiple expressions can be evaluated by using conditional operators:

Operator Description
and If an expression returns logical false it returns that value and doesn't evaluate the next expression. Otherwise it returns the value of the last expression.
or If an expression returns logical true it returns that value and doesn't evaluate the next expression. Otherwise it returns the value of the last expression.

Expressions are evaluated from left to right. Use parentheses to force precedence.

The following operators can be used to compare a file attribute to a value:

Operator Description
=, equal, equals equals to
>, greater than, greater greater than
>=, at least greater or equal
<, less than, less less than
<=, at most less or equal

A value must be of one of the data types listed below:

Type Description
string Quoted sequence of characters.
number Whole number.
time interval Time interval (number) with suffix. Supported suffixes are "minute(s)", "hour(s)" and "day(s)".
file size Units of space (number) with suffix. Supported suffixes are "byte(s)", "kilobyte(s)", "megabyte(s)" and "gigabyte(s)".
file type "file", "directory", "block", "character", "pipe", "link" or "socket".

The following file attributes are searchable:

Attribute Description Type Example
name case sensitive filename pattern string "*.txt"
iname case insensitive filename pattern string ""
regex case sensitive regular expression string ".*\.html"
iregex case insensitive regular expression string ".*\.TxT"
atime last access time time interval 1 minute
ctime last file status change time interval 15 hours
mtime last modification time time interval 30 days
size file size size 10 megabyte
group name of the group owning the file string "users"
gid id of the group owning the file number 1000
user name of the user owning the file string "john"
uid id of the user owning the file number 1000
type file type file type pipe
filesystem name of the filesystem the file is on string "ext4"

Additionally you can test these flags:

Flag Description
readable the file can be read by the user
writable the user can write to the file
executable the user is allowed to execute the file
empty the file is empty and is either a regular file or a directory

Differences to GNU find

Sometimes GNU find doesn't behave in a way an average user would expect. The following expression finds all documents in the current folder with a file size less or equal than 1G because every file with at least one byte is rounded up:

$ find . -size 1G

efind converts file sizes to byte to avoid this confusing behaviour:

$ efind . "size=1G" --print
$ find . -size 1073741824c

efind's --printf option is not fully compatible with GNU find:

  • In contrast to GNU find numeric values like file size or group id are not converted to string. This means that all number related flags work with efind.
  • Width and precision are interpreted exactly the same way as the printf C function does.
  • The fields %a, %c and %t print the timestamp in seconds.
  • Date format strings are not limited to a single field. The string "%AHMS" prints hour, minute and second of the last file access, for example.
  • efind's printf format supports user-friendly field names like "{path}" or "{group}".
  • When printing an undefined escape sequence (e.g. "\P") only the character following the backslash is printed.

Getting efind

You can build efind from source code or download a package for your distribution. If you should miss a package type or if you want to support efind don't hesitate to contact me. Any help is much appreciated :)