Gentoo Development Guide

find -- Finding Files

The find utility can be used to search for and perform commands upon groups of files matching a given set of criteria. The basic usage is find path rules.

For portability purposes, always specify a path. Do not rely upon find defaulting to the current working directory if no path is provided.

Useful rules include:

Rule Effect POSIX?
-name "blah" Only find files named blah. The * and ? wildcards may be used but should be quoted as in -name 'blah*'. yes
\! -name "blah" Only find files not named blah. yes
-type f Find only regular files, not directories. yes
-type d Find only directories. yes
-type l Find only symbolic links. yes
-user foo Find only files belonging to user foo. It is best to use named users rather than numeric UIDs. In particular, root may not be UID 0 on some systems. yes
-group foo Find only files belonging to group foo. It is best to use named groups rather than numeric GIDs. yes
-maxdepth 3 Only descend 3 levels into subdirectories. -maxdepth 1 will ignore all subdiretories of the specified path. no, GNU and BSD
-mindepth 2 Ignore the first 2 directory levels before a match occurs. -mindepth 1 will process all files except the command line arguments. no, GNU and BSD
-exec foo '{}' Execute a command. {} is replaced by the name of the current matched file. See examples below. yes
-execdir foo '{}' Same as -exec but runs the command from within the basedir of the match. no, GNU and BSD
-delete Delete the match. no, GNU and FBSD

Note

EAPI>=5 assumes GNU find, so it is safe to use GNU extensions in ebuild context for those EAPIs.

By default, find will echo a list of matching files to the standard output. This can be used in a while loop:

while read f ; do
    einfo "Doing unholy things to ${f}"
done < <(find "${S}" -type f)

Or a for loop (for small numbers of files):

for f in $(find "${S}" -type f) ; do
    einfo "Calling down holy vengance upon ${f}"
done

Warning

In both cases, files with weird characters or spaces in their names may cause serious problems.

As an alternative you can use the -exec argument. Be careful with escaping to ensure that bash doesn't gobble up the special characters:

find "${S}" -name '*.data' -exec mv '{}' "${S}/data/" \;

When -exec is terminated by a ; character (needs escaping or quoting) then the command line is built separately for every match. If it is terminated by a + character then the command line is built by appending each selected file name at the end.

The syntax below is useful if the command you want to run accepts multiple arguments such as doins and is more efficient in that case:

find "${S}" -name '*.so*' -exec doexe '{}' +

Find also supports negative matches:

find "${S}/bundled-libs" \! -name 'libbass.so' -delete

This will delete all files in the "bundled-libs" folder except "libbass.so". Make sure you always escape the ! character, so it's not interpreted by the shell.

Warning

The -exec argument has security issues, because of race conditions (this is also true for find . -print0 | xargs ... constructs). This should not be a problem in ebuild context, because directories typically aren't writeable by random users. However you should consider -execdir as an alternative approach which runs the command from inside the basedir of the match (note that -execdir is not POSIX, see the table).

See find-1 and IEEE1003.1-2004-find for further details and examples.