How to use the find Command on Linux
Finding files spread across a computer can be a challenge, GNU/Linux provides a
number of classic Unix tools to help alleviate that problem. Today we will be
focusing on the simplest of these tools: the find
command.
First appearing in Unix Version 5 in 1974 find
is a required standard in
Unix-like operating systems (POSIX). On Linux find is provided by the GNU
Findutils package.
find
— search for files in a directory hierarchy
find
is a tool for searching files by proprieties such as filename, file
size, last changed, and much more By default find
searches a directory and
its subdirectories recursively for a given combination of file properties
called and expression.
The layout of a typical find
command is as follows:
find [starting directory] [search expression]
find
will search the starting directory and all of its subdirectories for
files that match a search expression, outputting matched files.
For example, here is a search that looks through a copy of the Emacs source code searching for Emacs Lisp files (.el) that are not a test file:
find ~/Downloads/emacs -name '*.el' -not -name '*-tests.el' -type
If no directory is given then the current directory is used, so the following is the same as the above command:
cd ~/Downloads/emacs
find -name '*.el' -not -name'*-tests.el' -type f
If no expression is given find
will output all files and subdirectories
in the given directory, similar to the tree
command without the pretty
formatting.
Expressions
find
provides many different test expressions for searching file
properties. A few useful ones are listed below, the complete list can be
found in the find
man page under Tests.
-name pattern |
find files where filename matches pattern |
-path pattern |
find files where path matches pattern |
-user username |
find files owned by a user |
-readable |
match readable files |
-writable |
match writable files |
-perm mode |
match files with same permissions |
-type c |
find files of a specific type (f regular file, l link, d directory, s socket) |
-newer file |
find files newer that given file |
-amin n |
find files that has been accessed n minutes ago |
-atime n |
find files that has been accessed n days ago |
-mmin n |
find files that has been modified n minutes ago |
-mtime n |
find files that has been modified n days ago |
-size n |
match file size (follow n with c for bytes, k for KiB, M for MiB, G for GiB) |
Some important things to note:
-
Patterns should always be enclosed in 'single quotes' to avoid shell expansion
-
Pattern matching is case sensitive, case insensitive versions have a leading i e.g.
-iname
for case insensitive-name
. -
Any expression can search for the opposite by placing
-not
or!
before the test flag -
Numeric arguments, denoted by n, can search for greater than
+n
, exactlyn
, or less than-n
By default back-to-back tests are logically ANDed, meaning the results
must satisfy all of the restrictions given. These AND's can be explicitly
stated with the -and
or -a
flag.
For example, if I was trying to search for formatted document files
find ~/Documents -name '*.doc' -name '*docx' -name '*.odt'
find
returns no results as it is impossible for a file to end with 3
different extensions. We can fix this by ORing the tests with -or
/
-o
files need to only match one test or the other.
find ~/Documents \( -name '*.doc' -o -name '*.docx' -o -name '*.odt' \) -type f
The parts of an expression enclosed with parenthesis are evaluated first. Parenthesis must be escaped '\( \)' as they have a special meaning in the shell (the '\' tells the shell to ignore them). In this example, the filename must match one of the file extensions AND be a regular file.
Patterns and Regular Expressions
Patterns are limited to a basic shell pattern matching scheme where:
* |
matches any combination of zero or more characters |
? |
matches any one character |
[STRING] |
match if character contained in string or a range [a-z] / [0-9] |
find
also supports using regular expressions with a number of different
regex syntaxs supported, the default is Emacs style regular expressions.
A regex version of our document search would be:
find ~/Documents -regex '.*\.\(doc[x]?\|odt\)' -type f
Note that -regex
operates on the file path and not just the filename.
Execute Commands on find
Results
Now that you can get results from find
you'll want to use them. Before
piping the output of find
consider the following: do you want to pipe "to
the input of a program" or "to the arguments"? If it is the arguments piping
will not work instead use the -exec
flag.
Here's a command that moves recent photos from my SD card:
find "/mnt/SD" -iname '*.jpg' -ctime -2 -exec mv '{}' ~/Pictures/Lunch/ \;
In the -exec
flag curly brackets '{}
' will be replaced by the output from
find
. The '\;
' denotes the end of the command, which again must be
escaped as semicolons have a special meaning in the shell.
When ending -exec
with a semicolon the command will be invoked once for
every file found, very inefficient. A faster way would be append the
results to a list of arguments once. This can be done in find with:
find ~/Project/work/ -regex '.*\.\(c\|h\)' -type f -writable -exec emacs '{}' \+
The big limitation of the append option is the curly brackets must be the
last argument. For even more flexibility see the xargs
command included
with GNU findutils.
There is an interesting speed comparison of -exec
and xargs
options on
everythingcli.org.
Delete Files
You can delete files directly from find
with the -delete
flag. Warning
this is permanent and files will not be moved to the trash.
find ~/Downloads/ -maxdepth 1 \( -iname '*checksum*' -o -iname 'SHA[0-9]*' \) -delete
Deletes some old checksum files from the downloads folder.
Standards Compliance
Like most GNU utilities, GNU find
provides many extra features that may not
exist in other versions of find
. If you intent to the find
command in a
cross platform script you should take this seriously. See the "Standards
Conformance" section in the find(1)
man page, as well as the POSIX
find(1p)
man page.
See Also
-
GNU find(1) man page. (
man find
) -
GNU Findutils manual. GNU Project. (
info find
) -
Introduction to Linux Ch. 3 Sec 3.3: Finding files. Linux Documentation Project
-
find (Unix). Wikipedia
-
POSIX find(1p) man page. (
man 1p find
)