ff(1)

NAME
ff - Search for files in the filesystem

SYNOPSIS
ff [<options>] [<expression/directory> ... | [-D] <directory> ...]

DESCRIPTION
ff(1) is a tool for searching the filesystem for entries that all share a set of common features. It was inspired by fd(1) but is more powerful and versatile without being too complex. ff(1) aims to be a more user-friendly alternative to find(1).

ff(1)'s primary goal is to be an interactive tool that is intuitive, effective and easy to use. It is optimized for narrowing down a list of entries step by step. It lets you match many file attributes in many different ways and is extensible by plugins.

ff(1) takes a set of expressions and directories as arguments and uses them for searching. If no arguments are specified, ff(1) lists all files and directories below the directory you are currently in.

Whether an argument is an expression or a directory is detected automatically. Directories may be at the start or the end of the list of arguments. They are identified as directories when they contain at least one ’/' and point to an existing name in the filesystem. However, directories can be explicitly specified using the -D/--directories option, in which case auto-detection will not be used. If no directory argument is found the current directory is used as the starting point.

ff(1) uses parallel processes to speed up searching by default. The number of processes depends on the number of CPU cores and can be controlled with -j/--jobs.

OPTIONS
Global options:

--cache
    Location of the metadata cache (default: /home/lars/.cache/ff.db).

--no-cache
    Do not use the metadata cache.

-j, --jobs <num>
    Set number of processes to use for searching and executing (default: the number of CPU cores).

<expression/directory>
    An expression for matching files or a directory to search.

-D, --directories <path> [<path> ...]
    Search entries in these paths (default is current directory).

Commands:

-h, --help [<plugin>]
    Show this help message or the help message for a particular plugin.

--version
    Show program's version number and exit.

--list-attributes
    Show a list of available attributes to use for searching, sorting and output.

--list-plugins
    Show the list of available plugins.

--list-types
    Show the list of available types.

Search options:

-H, --hide
    Do not show hidden files and directories.

-I, --ignore
    Do not show files that are excluded by patterns from .(git|fd|ff)ignore files.

-e, --exclude <expression>
    Exclude entries that match the given expression.

-g, --glob
    Treat the pattern as a literal string.

-r, --regex
    Perform a regular-expression based search (default).

-F, --fixed-strings
    Treat the pattern as a literal string.

-c, --case <mode>
    How to treat the case of text attributes (smart, ignore or sensitive).

-a, --absolute-path
    Show absolute instead of relative paths.

-L, --follow
    Follow symbolic links.

-p, --full-path
    Search full path (default: file-/dirname only).

--one-file-system, --mount, --xdev
    Do not descend into different file systems.

Output options:

-x, --exec <cmd>
    Execute a command for each search result.

-X, --exec-batch <cmd>
    Execute a command with all search results at once.

-C, --color <when>
    When to use colors: never, *auto*, always.

-0, --print0
    Separate results by the null character.

-v, --verbose
    Produce output similar to `ls -l`.

-S, --sort [<attribute-list>]
    Sort entries by path or any other attribute.

-R, --reverse
    Reverse the sort order.

--count
    Count the attributes from <attribute-list> and print statistics, instead of the result, the default is to count the total size and the file types of the entries found. Add --json for JSON output.

-l, --limit N
    Limit output to at most N entries.

-1  Print only the first entry and exit immediately.

-o, --output <attribute-list>
    Print each entry by using a template of comma-separated attributes. The special value 'file' stands for all file attributes.

--sep
    Separate each attribute of --output with <string>, default is a single space.

--json
    Print attributes as one big json object to stdout.

--jsonl
    Print attributes as jsonl (one json object per line) to stdout.

--si
    Parse and print file sizes in units of 1K=1000 bytes instead of 1K=1024 bytes.

TESTS
All command line arguments that do not point to a directory will be used as test expressions. Each filesystem entry is matched against the list of these tests going from left to right. We start with a set of all entries, and the tests are used to narrow this set down, or remove particular entries from the set.

A test basically has the form:

    [<[plugin.]attribute><operator>]<value>
An test matches a certain <value> or pattern against a certain <attribute> of a filesystem entry. The type of test performed is denoted by the <operator>.

The simplest form of a test is to just specify <value>. It is a shorthand for

    file.name~<value>
which means that each entry's basename is matched against the regular expression <value>. (This default behavior can be changed with the -r/--regex, -F/--fixed-strings, -g/--glob and -p/--full-path options.)

It is good practice to use full attribute names and to quote either the value or the whole expression to prevent the shell from interfering with characters like '*', '(', ')', '<', '>', etc.

Tests can be grouped with 'AND' and 'OR' operators and parenthesis, whereas the 'AND' can be omitted, because it is redundant. Please note that parenthesis must be escaped or quoted properly to prevent the shell from interpreting them. Alternatively, you can use '{{' and '}}' instead.

ATTRIBUTES
ff(1) lets you search in a wide variety of file attributes. This list of attributes is provided by plugins. Essential plugins are built in, and you can also add your own plugins written in python(1).

You can list all available attributes this way: `ff --list-attributes`.

The full name of an attribute consists of the <plugin> name, a dot, and the <attribute> name. The plugin part of the attribute is optional unless the same attribute name is provided by multiple plugins. It will produce an error if an attribute name in an expression is ambiguous. An exception is the ’file' plugin whose attribute names are global, always take precedence and will never produce an error. For all other attributes it is recommended to always write the full attribute name including the <plugin> portion, e.g. to avoid possible runtime errors in shell scripts.

The builtin attributes are as follows:

[file.]path :: string
    The full pathname of the file. It will be relative to the current working directory depending on the <directory> arguments that were given on the command line. This can be changed with the -a/--absolute path option.

[file.]root :: string
    The start directory the file was found in.

[file.]relpath :: string
    The pathname of the file relative to the start directory.

[file.]dir :: string
    The dirname portion of the file.

[file.]name :: string
    The basename portion of the file

[file.]ext :: string
    The file extension without the leading dot or the empty string if the file has no extension.

[file.]pathx :: string
    The file path without the extension.

[file.]namex :: string
    The file basename without the extension.

[file.]device :: number
    The number of the device the file is located.

[file.]inode :: number
    The number of the inode of the file.

[file.]samedev :: boolean
    Whether the file is on the same device as the start directory.

[file.]depth :: number
    The depth of the file relative to the start directory.

[file.]type :: filetype
    The file type: one of 'd'/'directory', 'f'/'file', 'l'/'symlink', ’s'/'socket', 'p'/'pipe'/'fifo', 'char', 'block', 'door', 'port', ’whiteout' or 'other'.

[file.]exec :: boolean
    Whether the file is executable or not.

[file.]size :: size
    The size of the file in bytes. All types except 'file' have a size of 0.

[file.]mtime :: time
    The modification time of the file in seconds since epoch.

[file.]ctime :: time
    The inode change time of the file in seconds since epoch.

[file.]atime :: time
    The access time of the file in seconds since epoch.

[file.]time :: time
    An alias for 'mtime'.

[file.]mode :: mode
    The mode and permission bits of the file.

[file.]perm :: mode
    The permission bits of the file without the file type bits.

[file.]links :: number
    The number of links to the inode.

[file.]uid :: number
    The user id of the owner of the file.

[file.]gid :: number
    The group id of the owner of the file.

[file.]user :: string
    The user name of the owner of the file.

[file.]group :: string
    The group name of the owner of the file.

[file.]hide :: boolean
    Whether the the name of the file starts with a dot.

[file.]hidden :: boolean
    Whether the file is "hidden" or not, i.e. if one of the path components contains a leading dot.

[file.]empty :: boolean
    Whether the file or directory is empty or not.

[file.]link :: string
    The target path of a symbolic link relative to its parent directory. Empty if the file is not a symbolic link.

[file.]target :: string
    The full target path of a symbolic link. Empty if the file is not a symbolic link.

[file.]broken :: boolean
    Whether the target of a symbolic link points to a file that does not exist.

[file.]mime :: string
    The mime type of the file based on the file extension.

[file.]class :: string
    The leading component of the file's mime type.

[file.]text :: boolean
    Whether the file contains text or binary data.

[file.]mount :: boolean
    Whether the entry is a mountpoint.

There are also some attributes available for media files. Their availability depends on the presence of the 'pymediafile' python module.

medium.duration :: duration
    The duration of a medium (audio, video) in seconds.

medium.artist :: string
    The artist audio tag of the file.

medium.album :: string
    The album audio tag of the file.

medium.title :: string
    The title audio tag of the file.

medium.genre :: string
    The genre audio tag of the file.

medium.date :: string
    The date audio tag of the file.

medium.format :: string
    The format of an image ('png', 'jpeg', etc.) in case the file is an image.

medium.width :: number
    The width of a visual medium (image, video) in pixel.

medium.height :: number
    The height of a visual medium (image, video) in pixel.

TYPES
Each attribute has been assigned a certain type that describes how its value is supposed to be interpreted and which operators it supports. Beside the usual 'string', 'number' and 'boolean' types there are types for file sizes, file permissions, timestamps, durations etc.

Durations consist of one or more partial time designations that are summed up, e.g.:

    1h30m25s
The valid units are: 's' for seconds, 'm' for minutes, 'h' for hours, 'd' for days, 'w' for weeks (7 days), 'M' for months (30 days) and 'y' for years (365 days). If no unit is given 'm' for minutes is assumed.

There are a number of predefined date and time parsing patterns for attributes providing a 'time' type.

- YY-mm-dd HH:MM:SS

- YY-mm-dd HH:MM

- YYmmddHHMM

- YY-mm-dd

- YYmmdd

- HH:MM:SS

- HH:MM

- HHMM

OPERATORS
The third component in a test beside the <attribute> and the <value> is the <operator>.

There are operators for numbers:

=   attribute is equal to <value>

+= >=
    attribute is greater than or equal to <value>

-= <=
    attribute is less than or equal to <value>

+ > attribute is greater than <value>

- < attribute is less than <value>

Please note that the > and < characters must be properly quoted to avoid being interpreted as redirections by the shell, which is why the + and - forms are preferred.

Operators for strings:

=   attribute is equal to <value>

:   contains substring <value>

~   matches regular expression <value>

%   matches glob pattern <value>

Operators for lists of strings:

=   one string in the list is equal to <value>

:   one string contains substring <value>

~   one string matches regular expression <value>

%   one string matches glob pattern <value>

Operators for booleans:

=   attribute is equal to <value>, which may be one of (true, t, 1, yes, y, on) or (false, f, 0, no, n, off). The case is ignored.

Operators for mode:

=   all bits from the attribute are exactly equal to <value>

:   all bits that are set in <value> are also set in the attribute

~   any of the bits that are set in <value> are set in the attribute

FILE REFERENCES
It is possible to pass a path of a file as reference instead of a value. To use a reference you pass a '{}' followed by the path name as the value. For example, to find all files newer than foo/bar/example.txt you do:

    ff mtime+{}foo/bar/example.txt
The default behavior is to use the same attribute of the referenced file as the one it is supposed to be compared to, but it is also possible to use a different one:

    ff mtime+{atime}foo/bar/example.txt

OUTPUT
The contents of what is printed to standard output can be controlled using the -o/--output and the --sep options. -o/--output is a comma-separated list of attribute names, that will be printed using the separator string from the --sep option. -o/--output defaults to 'path'.

The -v/--verbose option produces output in the style of 'ls -lh'.

The --json and --jsonl options print each record as a JSON object to standard output. The attributes of the JSON object are the same as in -o/--output. The difference between both options is that --json produces one big JSON list object containing all the records, whereas the --jsonl prints one JSON object per record per line.

By default, pathnames are printed in color according to dircolors(1) rules, unless NO_COLOR is set, --color=never, or ff(1)'s output is not connected to a terminal. Color output can be forced with --color=always.

EXECUTION
The -x/--exec and -X/--exec-batch options allow to execute commands with search results as arguments. -x/--exec starts one subprocess for every search result, whereas -X/--exec-batch starts only one subprocess that gets all search results at once. The exit status of ff(1) will be set accordingly if one of the commands terminates with an error, see EXIT CODES below:

The following placeholders are substituted in the command:

{}  full path, alias for {path}

{/} basename, alias for {name}

{//}
    parent directory, alias for {dir}

{.} path without file extension, alias for {pathx}

{/.}
    basename without file extension, alias for {namex}

{..}
    file extension, alias for {ext}

{attribute}
    replaced with the value of attribute

PLUGINS
It is possible to write your own plugins and extend ff(1)'s functionality. A plugin is an ordinary python module. There are many examples included in the source distribution and a plugin_template.py. User plugins are imported from ~/.ff.

EXCLUSION
The -e/--exclude option allows to exclude entries that match the <expression>. Excluding takes place before all other tests are evaluated. If a directory matches it will not be descended into, so entries below it will not be produced.

Please note: Unless -H/--hidden is given, all hidden files will be excluded using this method (the same as '--exclude hide=yes'). So it is not possible to find hidden entries with

    ff hidden=yes
unless -H/--hidden is specified. The same applies to -I/--ignored.

IGNORE FILES
By default, ff(1) reads .gitignore, .ignore, .fdignore, and .ffignore files and excludes all entries that match the set of patterns in one of these files. The ignore syntax is described in gitignore(5).

SORTING
Sorting is controlled with -S/--sort option. It is off by default, this way entries are processed and printed as they are found. This makes better use of ff(1)'s parallel processing capabilities and is much faster.

-S/--sort takes an optional <attribute-list> argument. Without it, sorting is done alphabetically on the entry's path. <attribute-list> is a comma-separated list of attribute names that will be used as sort criteria. The order can be reversed with -R/--reverse.

COUNTING
If the --count option is specified, instead of printing the search result, count the entries and the attributes from <attribute-list> and print these counts to standard output. If --count is given without a list of attributes the total file size and statistics about the different file types is displayed. If <attribute-list> is present a total or a count of these attributes is done. There is always a "_total" field that contains the number of all entries that matched.

There are two ways of counting attributes that depend on their type. Types like file size or duration that vary widely are summed up to a total and for all other types each individual value is counted. This way you can get an overview on the variety of values of an attribute. For some attributes --count makes not much sense, e.g. path or time. It is best suited for attributes like type, perm, hidden, depth, uid, gid, etc.

The way a type is counted can be checked with --list-types.

EXAMPLES
Find only regular files in the current directory and all its subdirectories:

      $ ff -tf
Find only hidden files in directory /home/user:

      $ ff -H hidden=yes /home/user
Find files matching the glob pattern:

      $ ff -g '*.txt'
Find files executable by the user:

      $ ff type=f perm:700
      $ ff type=f perm:u+x
      $ ff exec=yes

GET HELP
View a list of available plugins:

    $ ff --list-plugins
Get help on a specific plugin, including the attributes it provides:

    $ ff --help <plugin>
View a list of all available attributes:

    $ ff --list-attributes
View a list of all available types and their supported operators:

    $ ff --list-types

EXIT CODES

0   Everything went fine.

1   There was an error in the arguments provided by the user.

2   One or more --exec or --exec-batch subprocesses had errors.

3   One or more ff processes had unrecoverable errors.

10  A plugin had an unrecoverable error.

11  An attribute was specified that does not exist.

12  There was an error in a test expression.

ENVIRONMENT

FF_OPTIONS
    Default options to use for every invocation of ff(1).

FF_PLUGIN_DIRS
    A colon-separated list of additional directories from which to load plugins.

LS_COLORS
    A list of dircolors rules, see dircolors(1) and dir_colors(5).

NO_COLOR
    Do not produce colorful terminal output regardless of ff(1)'s options.

SEE ALSO
find(1) fd(1)

AUTHOR
Lars Gustaebel <lars@gustaebel.de>

https://github.com/gustaebel/ff/