This article needs additional citations for verification .(June 2016) |
find | |
---|---|
Original author | Dick Haight |
Developer | AT&T Bell Laboratories |
Operating system | Unix, Unix-like, Plan 9, IBM i |
Platform | Cross-platform |
Type | Command |
find
is a shell command that locates files [1] based on search criteria and performs actions on the matching files such as printing the file system path to standard output. It starts searching at a root directory of a hierarchical structure and recursively traverses the tree although can be limited to a maximum number of levels. Commonly used search criteria include file name pattern matching and time range matching for last modification or last access. With no arguments, the command outputs the path of each file in the tree rooted at the working directory. The command can search through different file systems of partitions belonging to one or more storage devices mounted under the starting directory. [2] The command is available on most Unix-like systems.
The command first appeared in Version 5 Unix as part of the Programmer's Workbench project, and was written by Dick Haight alongside cpio, [3] which were designed to be used together. [4]
The GNU implementation was originally written by Eric Decker. It was later enhanced by David MacKenzie, Jay Plett, and Tim Wood. [5]
The command was ported to the IBM i operating system. [6]
The BusyBox computer program provides the find
command and many other commands in a single executable file.
The syntax of the command can be described as:
$ find [-H|-L] path... [expression]
Traditionally, at least one path must precede the expression but newer versions allow for no path argument; defaulting to the working directory.
The expression can specify various aspects including match criteria and actions to perform on matched files. Expression elements are separated by whitespace and are evaluated left-to-right. The command can match via wildcard characters but wildcard match text must be quoted to prevent shell globbing. If the expression is omitted, then all files are matched.
The GNU implementation has features beyond the POSIX specification.
The expression specifies the behavior of the command including what files to select (sometimes called predicate) and what to do with each matching file (sometimes called action). The elements of an expression commonly include:
-name pattern
-type type
b
: block device (buffered) c
: character device (unbuffered) d
: directory f
: regular file l
: symbolic link p
: named pipe s
: socket D
: door -print
-print0
, -exec
, or -ok
) the action of -print
is performed.-print0
-exec program [argument...] ;
{}
, it is replaced with the candidate path. POSIX doesn't specify what happens if multiple {}
are specified. Most implementations replace each {}
with the candidate path.-exec program [argument...] {} +
-ok program [argument...] ;
-exec program [arguments...] ;
, otherwise the command is not run for the candidate path and the file is not selected.-maxdepth
-maxdepth 2
limits searching to the root directory and its direct children.Operators are used to combine expressions elements. Operators are listed in order of decreasing precedence:
( expr )
; Selects evaluation order of subexpression.! expr
; true if expr
is false.expr1 expr2
or expr1 -a expr2
; expr2
is not evaluated if expr1
is false.expr1 -o expr2
; expr2
is not evaluated if expr1
is true.The following command searches the current working directory tree for files named A
or B
.
$ find.-nameA-o-nameB
The following command searches the current working directory tree except the subdirectory tree ".svn" for files named "foo.cpp". Operator !
is quoted so that it's not interpreted as the history substitution character.
$ find.-name'foo.cpp''!'-path'.svn'
In light of the fact that a file system can contain looped structures via hard and soft links, POSIX requires that the command detect infinite loops; that is, entering a previously visited directory that is an ancestor of the last file encountered. When it detects an infinite loop, the command must write a diagnostic message to standard error plus either recover its position in the hierarchy or terminate.
The -H
and -L
options, specified in the POSIX standard, control how the command handles symbolic links. The default behavior is to not follow symbolic links. The -L
option causes the command to follow symbolic links. The -H
option causes the command to follow symbolic links while processing the command line arguments. [7] A common extension is the -P
option, for explicitly disabling symlink following. [8] [9]
The following command searches the current working directory tree for files named starting with my. The single quotes avoid the shell expansion. Without them, the shell would replace my* with the list of files whose names begin with my in the current working directory which is not necessarily the same as the files matching in subdirectories.
$ find.-name'my*'
The following command includes -type f
to limit results to regular files; excluding other file system items such as directories and symbolic links.
$ find.-typef
The following command includes the -ls
action option to include detailed file information like from command ls -a
.
$ find.-ls
The following command searches every directory except the subdirectory tree excluded_path (full path including the leading /) that is pruned by the -prune
action, for a regular file whose name is myfile.
$ find/-pathexcluded_path-prune-o-typef-namemyfile-print
The following command searches the /home/weedly directory tree for regular files named myfile. You should always specify the directory to the deepest level you can remember.
$ find/home/weedly-namemyfile-typef-print
The following command searches the local subdirectory tree of the current working directory and the /tmp directory tree for directories named mydir.
$ findlocal/tmp-namemydir-typed-print
The -ls
operator prints extended information, and the example finds any regular file whose name ends with either 'jsp' or 'java'. Note that the parentheses are required. In many shells the parentheses must be escaped with a backslash (\(
and \)
) to prevent them from being interpreted as special shell characters. The -ls
operator is not available on all versions of find
.
$ find.\(-name'*jsp'-o-name'*java'\)-typef-ls
The following command changes the permissions of all regular files whose names end with .mp3 in the directory tree /var/ftp/mp3. The action is carried out by specifying the statement -exec chmod 644 {} \;
in the command. For every regular file whose name ends in .mp3
, the command chmod 644 {}
is executed replacing {}
with the name of the file. The semicolon (backslashed to avoid the shell interpreting it as a command separator) indicates the end of the command. Permission 644
, usually shown as rw-r--r--
, gives the file owner full permission to read and write the file, while other users have read-only access. In some shells, the {}
must be quoted. The trailing ";
" is customarily quoted with a leading "\
", but could just as effectively be enclosed in single quotes.
$ find/var/ftp/mp3-name'*.mp3'-typef-execchmod644{}\;
Note that the command itself should not be quoted; otherwise you get error messages like
find: echo "mv ./3bfn rel071204": No such file or directory
which means that find
is trying to run a file called 'echo"mv ./3bfn rel071204"
' and failing.
If you will be executing over many results, it is more efficient to use a variant of the exec primary that collects file names up to ARG_MAX and then executes COMMAND with a list of file names.
$ find.-execCOMMAND{}+
This will ensure that file names with whitespaces are passed to the executed COMMAND
without being split up by the shell.
The -delete
action is a GNU extension, and using it turns on -depth
. So, if you are testing a find command with -print
instead of -delete
in order to figure out what will happen before going for it, you need to use -depth -print
.
Delete empty files and print the names (note that -empty
is a vendor unique extension from GNU find
that may not be available in all find
implementations):
$ find.-empty-delete-print
Delete empty regular files:
$ find.-typef-empty-delete
Delete empty directories:
$ find.-typed-empty-delete
Delete empty files named 'bad':
$ find.-namebad-empty-delete
To prevent deleting all files, the -delete
option should only be used with selection options such as -empty
or -name
. The following command deletes all files a directory tree.
$ find.-delete
The following command searches for files in the /tmp directory tree for a string:
$ find/tmp-typef-execgrep'search string'/dev/null'{}'\+
The /dev/null
argument is used to show the name of the file before the text that is found. Without it, only the text found is printed. (Alternatively, some versions of grep support a -H flag that forces the file name to be printed.) GNU grep
can be used on its own to perform this task:
$ grep-r'search string'/tmp
The following command searches for "LOG" in jsmith's home directory tree.
$ find~jsmith-execgrepLOG'{}'/dev/null\;-print /home/jsmith/scripts/errpt.sh:cp $LOG $FIXEDLOGNAME/home/jsmith/scripts/errpt.sh:cat $LOG/home/jsmith/scripts/title:USER=$LOGNAME
The following commands searches for the string "ERROR" in all XML files in the current working directory tree:
$ find.-name"*.xml"-execgrep"ERROR"/dev/null'{}'\+
The double quotes (") surrounding the search string and single quotes (') surrounding the braces are optional in this example, but needed to allow spaces and some other special characters in the string. Note with more complex text (notably in most popular shells descended from `sh` and `csh`) single quotes are often the easier choice, since double quotes do not prevent all special interpretation. Quoting file names which have English contractions demonstrates how this can get rather complicated, since a string with an apostrophe in it is easier to protect with double quotes:
$ find.-name"file-containing-can't"-execgrep"can't"'{}'\;-print
$ find.-user<userid>
The following command matches file names ignoring case. The -iname
option is not POSIX required.
$ find.-iname'MyFile*'
If the -iname
switch is not supported on your system then workaround techniques may be possible such as:
$ find.-name'[mM][yY][fF][iI][lL][eE]*'
The following command searches for files sized between 100 kilobytes and 500 kilobytes.
$ find.-size+100k-a-size-500k
Date ranges can be used to, for example, list files changed since a backup.
-mtime
: modification time-ctime
: inode change time-atime
: access timeFiles modified a relative number of days ago:
-daystart
to measure time from the beginning of a day (0 o'clock) rather than the last 24 hours.The following command searches for text files in the document folder modified since one week.
$ find~/Documents/-iname"*.txt"-mtime-7
Files modified before or after an absolute date and time:
-newermt YYYY-MM-DD
: Last modified after date-not -newermt YYYY-MM-DD
: Last modified before dateExample to find all text files last edited in February 2017:
$ find~/Documents/-iname"*.txt"-newermt2017-02-01-not-newermt2017-03-01
-newer [file]
: More recently modified than specified file. -cnewer
: Same with inode change time.-anewer
: Same with access time.-not
for inverse results or range.List all text files edited more recently than "document.txt":
$ find~/Documents/-iname"*.txt"-newerdocument.txt
grep
find
dir
/s
option to recursively search for files or directories. tree
walk
and sor
find
. walk
finds files in a directory tree and prints the names and sor
filters (like grep
) by evaluating expressions in the form of a shell script. The commands are not part of Plan 9 from User Space, so Google's Benjamin Barenblat has a ported version to POSIX systems available through GitHub. [10] fd
find
written in Rust. [11] locate
locate
can exceed that of find
, but results can be inaccurate if the database is out-of-date. Typically, the database is updated from file system information via a find
command run periodically by a cron
job.find