Find
find(1) is a file finder.
Contents
Installation
find(1) will be pre-installed on any Linux or BSD operating system, as a POSIX utility.
Usage
Basic usage:
find . -name '*.zip'
The pattern is a glob shell expression, not a regular expression pattern. The options available are:
? as a wildcard
* as zero or more wildcards
character ranges like [0-9]
But to ensure that the glob is not eagerly evaluated by the shell, the pattern must be quoted.
Furthermore, note that the pattern is checked against the basename of the directory entry. The only possible match to a pattern that includes a / is the root directory itself.
Options
Options |
Meaning |
Example |
-name 'pattern' |
Filter to entries with a basename matching a pattern |
-name '*.zip' |
-type [df] |
Filter to files or directories |
-type f |
-user name |
Filter to entries owned by a user |
-user root |
-group name |
Filter to entries owned by a group |
-group root |
-perm octal |
Filter to entries with specific permissions |
-perm 775 |
-not |
Invert a subsequent filter |
-not -perm 775 |
-mindepth int |
Only search subdirectories some layers deep |
-mindepth 1 |
-maxdepth int |
Stop searching subdirectories at some layers deep |
-maxdepth 1 |
-mindepth and -maxdepth are global options, so must precede any other options.
$ find . -name '*.txt' -maxdepth 1 find: warning: you have specified the global option -maxdepth after the argument -name, but global options are not positional, i.e., -maxdepth affects tests specified before it as well as those specified after it. Please specify global options before other arguments. $ find . -maxdepth 1 -name '*.txt' [trim]
Command Execution
find(1) can execute a command on all still-matching files.
The -exec option consumes all subsequent arguments up to an escaped delimiter, i.e. \;.
If one of those arguments contains {}, that is expanded into the filename.
Note that there should only be one {}. Behavior for additional instances is undefined, non-portable, and unsupported.
- The arguments are executed in a subshell.
- Note then that any environmental variables and functions are not shared.
- The return code of the subshell determines if the option is considered a match or non-match
The -exec option can be used to implement custom filters. For example:
find somedir -name '' -exec grep --fixed-strings '<!--nomin-->' --quiet {} \;
The -exec option can also be used for scripting, to execute some action on all matches. For example:
Try:
find somedir -name '*.min.js' -exec cp {} ../production/ \;
Tips
find(1) operates from the working directory and prints filenames accordingly. That is...
if called like find ., all filenames will be printed starting with ./.
if called like find .., all filenames will be printed starting with ../.
if called with an absolute directory like find /etc, all filenames will be printed as absolute, too.
Furthermore, any subshells started by the -exec option operate in the working directory.
This can be tricky and inconvenient for scripting. Consider:
Always call with an absolute directory. For example: find "$(realpath somedir) ...
Change directory instead of passing a directory. For example: cd somedir && find . ...
Check if your find(1) implementation supports the -execdir option. This flag mirrors -exec except that...
- if a file is matched, the execution occurs in the same directory as that file.
- if a directory is matched, the execution occurs in the parent directory.
find(1) should never be piped directly into another command. If the -exec option is insufficient, the safe ways to use the output of find(1) are:
while IFS= read -r -d '' file; do echo "$file" done < <(find . -name '*.zip' -print0)
find . -name '*.zip' -print0 | xargs -0 echo