find
The command find
searches the filesystem for files based on their metadata.
The metadata that can be used to search for files includes, but is not limited
to a file’s:
Unlike search mechanisms found outside a terminal (like Window Search or Apple’s
Spotlight) which only list the files found, find
can do things to the files it
finds. The tasks you can have find
do are limited only by your imagination.
The syntax for find
is:
find [-H] [-L] [-P] [-D debugopts] [-Olevel] [path...] [expression]
but the key to using find is in the path and expression arguments, which can be complex.
The optional path
arguments tell find
where to begin looking for files. If
not given, the current directory is used.find
will ordinarily enter
subdirectories, but not parent directories of the given paths.
A good practice is to explicitly enter the path .
to search the current
directory, even though it is the default path.
The expression
is made up of option switches, tests, and actions, each
separated by an operator. The format of these expression elements varies, and
are fully documented in the manual page man find
. There are too many
expression elements to cover here, but below are listed the ones that we think are
the most useful or noteworthy.
Options affect the behavior of find
as a whole. Commonly used options include:
-depth
Deleting directories requires they be empty, so some actions like -delete
will imply -depth
automatically.
-maxdepth LEVEL
Do not confuse -maxdepth
with -depth
: they have completely different
behaviours and uses.
-mindepth LEVEL
-help
Tests are used to compare a file against some reference. If the test comparison
yields true, the next test or action in the expression (read left to right) is
applied. If a test yields false, find
moves on to the next file. Commonly used
tests include:
-name PATTERN
-iname PATTERN
-name
is
case-sensitive, whereas -iname
is case-insensitive. The PATTERN
can
include wildcard characters.Common wildcards include:
*
which matches any number of any characters,
?
which matches one position of any character, and
[ EXPR ]
will match a POSIX bracket expression in one position.
The syntax for bracket expressions is beyond the scope of this tutorial but
we’ll see some examples of what they look like.
-regex REGEXP
Regular expressions are an extremely powerful means of matching patterns. They are used in many places and are worth learning, but deserve a treatment in their own right.
-size n[bcwkMG]
-readable
-writeable
-executable
-type c
c
where c
is typically one ofd
for directory,f
for regular file, orl
for symbolic link. Other types also exits.-mtime [+-]N
-ctime [+-]N
-atime [+-]N
+
(-
), times greater (less) than N days ago are
matched.Actions do something, either emit a response from find
or run an arbitrary
command on a matched file. By default, find
does the action -print
when it
matches a file, which prints the full file name (with path starting from a
path argument) separated by a new line. Commonly used actions include:
-exec CMD {};
-execdir CMD {};
CMD
. The command can be
anything. All arguments following -exec
are assumed to be part of the
command until the first occurance of ;
. The (optional) characters {}
, if
encountered in the command expression, are replaced with the path to the
currently examined file. If you used -execdir
, find will run the command
from the subdirectory containing the matched file.-ok CMD ;
-exec
but prompts the user before executing the command. Very useful
if your expression may alter the file. It cannot take {}
to represent the
current matched file, so use it in conjunction with -exec
as needed for
safety.-print
-printf FORMAT
-quit
-prune
Operators group expression elements together and allow for logic matching. The operators, in decending order of precedence, are:
( EXPR )
! EXPR
-not EXPR
EXPR1 EXPR2
EXPR1 -a EXPR2
EXPR1 -and EXPR2
By default, if two expressions are given without an operator joining them, the
operator -and
is assumed.
EXPR1 -o EXPR2
EXPR1 -or EXPR2
EXPR1 , EXPR2
Be mindful of the Spaces surrounding everything! Each of the
expression elements is technically a command argument. As said earlier, all
arguments must be separated by a space. This includes (
and )
Many shells treat the characters *[]{}()?$
amongst others as special
operators. To prevent your shell from altering any input to find
, wrap
expressions in quotations as necessary. If in doubt, use quotes.
Print all regular files named exactly “.bashrc” within and below ~
:
$ find ~ -type f -name bash.rc
Print all regular files ending in “rc” within ~
and below:
$ find ~ -type f -name "*rc"
Print all files (regular and directories) ending in “rc” within ~
:
$ find ~ -name "*rc"
Print only directories one level into /etc
that are 3 characters
long which end with “sh” or “sl”
$ find /etc -maxdepth 1 -type d -name "?s[hl]"
Find all files in ~
ending with “.jpg” or “.png” in any case that were created
within the last 2 days.
$ find ~ -type f \( -iname "*.jpg" -or -iname "*.png" \) -and -ctime -2
Find all the files strictly in /tmp
named “data_NN.dat” where NN runs from
00-99 and run the command ls -l FILE
on each of them:
$ find /tmp -maxdepth 1 -type f -iname "data_[0-9][0-9].dat" -execdir ls -l {} \;
Have you ever needed to analyze hundreds of data files? Imagine if instead of
calling ls
on these files, you called a program that you wrote to analyze that
data. This is a quick way to generate those hundreds of plots you need to
process from your research data.