A mini-tutorial on the Unix/Linux find command
Posted by Martin Perron on Mar 10, 2008 in HowTo - Linux • 5 commentsLocating Files:
find command is used to locate files on a Unix or Linux system. find will search any set of directories you specify for files that match the supplied search criteria. You can search for files by name, owner, group, type, permissions, date, and other criteria. The search is recursive in that it will search all subdirectories too. The syntax looks like this:
find where-to-look criteria what-to-do
All arguments to find are optional, and there are defaults for all parts. (This may depend on which version of find is used. Here we discuss the freely available GNU version of find, which is the version available on YborStudent.) For example where-to-look defaults to . (that is, the current working directory), criteria defaults to none (that is, show all files), and what-to-do (known as the find action) defaults to -print (that is, display found files to standard output).
For example:
find
will display all files in the current directory and all subdirectories. The commands
find . -print
find .
do the exact same thing. Here’s an example find command using a search criteria and the default action:
find / -name foo
will search the whole system for any files named foo and display them. Here we are using the criteria -name with the argument foo to tell find to perform a name search for the filename foo. The output might look like this:
/home/wpollock/foo
/home/ua02/foo
/tmp/foo
If find doesn’t locate any matching files, it produces no output.
The above example said to search the whole system, by specifying the root directory (
) to search. If you don’t run this command as root, /find will display a error message for each directory on which you don’t have read permission. This can be a lot of messages, and the matching files that are found may scroll right off your screen. A good way to deal with this problem is to redirect the error messages so you don’t have to see them at all:
find / -name foo 2>/dev/null
Other Features And Applications:
-print action lists the files separated by a space when the output is piped to another command. This can lead to a problem if any found files contain spaces in their names, as the output doesn’t use any quoting. In such cases, when the output of find contains a file name such as foo bar and is piped into another command, that command seestwo file names, not one file name containing a space.In such cases you can specify the action
-print0 instead, which lists the found files separated not with a space, but with a null character (which is not a legal character in Unix or Linux file names). Of course the command that reads the output of find must be able to handle such a list of file names. Many commands commonly used with find (such as tar or cpio) have special options to read in file names separated with nulls instead of spaces.You can use shell-style wildcards in the -name search argument:
find . -name foo\*bar
This will search from the current directory down for foo*bar (that is, any filename that begins with foo and ends with bar). Note that wildcards in the name argument must be quoted so the shell doesn’t expand them before passing them to find. Also, unlike regular shell wildcards, these will match leading periods in filenames. (For example
.)find -name \*.txt
You can search for other criteria beside the name. Also you can list multiple search criteria. When you have multiple criteria any found files must match all listed criteria. That is, there is an implied Boolean AND operator between the listed search criteria. find also allows OR and NOT Boolean operators, as well as grouping, to combine search criteria in powerful ways (not shown here.)
Here’s an example using two search criteria:
find / -type f -mtime -7 | xargs tar -rf weekly_incremental.tar
gzip weekly_incremental.tar
will find any regular files (i.e., not directories or other special files) with the criteria
, and only those modified seven or fewer days ago (-type f
). Note the use of -mtime -7xargs, a handy utility that coverts a stream of input (in this case the output of find) into command line arguments for the supplied command (in this case tar, used to create a backup archive). 1
Another use of xargs is illustrated below. This command will efficiently remove all files named core from your system (provided you run the command as root of course):
find / -name core | xargs /bin/rm -f
find / -name core -exec /bin/rm -f ‘{}’ \; # same thing
find / -name core -delete # same if using Gnu find
(The last two forms run the rm command once per file, and are not as efficient as the first form.)
One of my favorite find criteria is to locate files modified less than 10 minutes ago. I use this right after using some system administration tool, to learn which files got changed by that tool:
find / -mmin -10
(This search is also useful when I’ve downloaded some file but can’t locate it.)
Another common use is to locate all files owned by a given user (
). This is useful when deleting user accounts.-user username
You can also find files with various permissions set.
means to find files with any of the specified permissions on, -perm /permissions
means to find files with all of the specified permissions on, and -perm -permissions
means to find files with exactly permissions. Permisisons can be specified either symbolically (preferred) or with an octal number. The following will locate files that are writeable by -perm permissionsothers
:
find . -perm +o=w
(Using -perm is more complex than this example shows. You should check both the POSIX documentation for find (which explains how the symbolic modes work) and the Gnu find man page (which describes the Gnu extensions).
When using find to locate files for backups, it often pays to use the
option, which forces the output to be depth-first—that is, files first and then the directories containing them. This helps when the directories have restrictive permissions, and restoring the directory first could prevent the files from restoring at all (and would change the time stamp on the directory in any case). Normally, -depthfind returns the directory first, before any of the files in that directory. This is useful when using the
action to prevent -prunefind from examining any files you want to ignore:
find / -name /dev -prune | xargs tar …
When specifying time with find options such as -mmin (minutes) or -mtime (24 hour periods, starting from now), you can specify a number
to mean exactly nn,
to mean less than -nn, and
to mean more than +nn. 2 For example:
find . -mtime 0 # find files modified within the past 24 hours
find . -mtime -1 # find files modified within the past 24 hours
find . -mtime 1 # find files modified between 24 and 48 hours ago
find . -mtime +1 # find files modified more than 48 hours ago
find . -mmin +5 -mmin -10 # find files modifed between 6 and 9 minutes ago
The following displays non-hidden (no leading dot) files in the current directory only (no subdirectories), with an arbitrary output format (see the man page for the dozens of possibilities with the -printf action):
find . -maxdepth 1 -name ‘[!.]*’ -printf ‘Name: %16f Size: %6s\n’
As a system administrator you can use find to locate suspicious files (e.g., world writable files, files with no valid owner and/or group, SetUID files, files with unusual permissions, sizes, names, or dates). Here’s a final more complex example (which I save as a shell script):
find / -noleaf -wholename ‘/proc’ -prune \
-o -wholename ‘/sys’ -prune \
-o -wholename ‘/dev’ -prune \
-o -wholename ‘/windows-C-Drive’ -prune \
-o -perm -2 ! -type l ! -type s \
! \( -type d -perm -1000 \) -print
This says to seach the whole system, skipping the directories /proc, /sys, /dev, and /windows-C-Drive (presumably a Windows partition on a dual-booted computer). The -noleaf option tells find to not assume all remaining mounted filesystems are Unix file systems (you might have a mounted CD for instance). The
is the Boolean OR operator, and -o
is the Boolean NOT operator (applies to the following criteria). So this criteria says to locate files that are world writable (!
) and NOT symlinks (-perm -2
) and NOT sockets (! -type l
) and NOT directories with the sticky (or text) bit set (! -type s
). (Symlinks, sockets and directories with the sticky bit set are often world-writable and generally not suspicious.)! \( -type d -perm -1000 \)
A common request is a way to find all the hard links to some file. Using
will tell you how many hard links the file has, and the inode number. You can locate all pathnames to this file with:ls -li file
find mount-point -xdev -inum inode-number
Since hard links are restricted to a single filesystem, you need to search that whole filesystem so you start the search at the filesystem’s mount point. (This is likely to be either
or /home
for files in your home directory.) The /
options tells -xdevfind to not search any other filesystems.
(While most Unix and all Linux systems have a find command that supports the
criteria, this isn’t POSIX standard. Older Unix systems provided the -inum
command instead that could be used for this.)ncheck
Using -exec Efficiently
The -exec option to find is great, but since it runs the command listed for every found file, it isn’t very efficient. On a large system this makes a difference! One solution is to combine find with xargs as discussed above:
find whatever… | xargs command
However this approach has two limitations. Firstly not all commands accept the list of files at the end of the command. A good example is cp:
find . -name \*.txt | xargs cp /tmp # This won’t work!
(Note the Gnu version of cp has a non-POSIX option
for this.)-t
Secondly filenames may contain spaces or newlines, which would confuse the command used with xargs. (Again Gnu tools have options for that,
.)find ... -print0 |xargs -0 ...
There are POSIX (but non-obvious) solutions to both problems. An alternate form of -exec ends with a plus-sign, not a semi-colon. This form collects the filenames into groups or sets, and runs the command once per set. (This is exactly what xargs does, to prevent argument lists from becoming too long for the system to handle.) In this form the {} argument expands to the set of filenames. For example:
find / -name core -exec /bin/rm -f ‘{}’ +
This form of -exec can be combined with a shell feature to solve the other problem. The POSIX shell allows us to use:
sh -c ‘command-line‘ [ command-name [ args... ] ]
(We don’t usually care about the command-name, so X
, dummy
, or inline cmd
is used.) Here’s an example of efficiently copying found files, in a POSIX-compliant way 3:
find . -name ‘*.txt’ -exec sh -c ‘cp “$@” /tmp’ dummy {} +
Or even better:
find . -name ‘*.txt’ -type f \
-exec sh -c ‘exec cp -f “$@” /tmp’ find-copy {} +
The find command can be amazingly useful. See the man page to learn all the criteria and options you can use.
Footnotes: Back
- Using the
taroption
is dangerous here;-cxargsmay invoketarseveral times if there are many files found and each
will cause-ctarto over-write the previous invocation. The
option appends files to an archive. Other options such as those that would permit filenames containing spaces would be useful in a-rproduction quality
backup script. - Note that fractional 24-hour periods are truncated! That means that
says to match files modified two or more days ago.find -mtime +1 - Posted on comp.unix.shell netnews newsgroup on Oct. 28 2007 by Stephane CHAZELAS.

I’m having an issue with gnu’s find, versus Mac/darwin’s find that is bedeviling me and I’m hoping you can help.
On my Mac OS X/Tiger system, I have three versions of find:
/usr/bin/find (which doesn’t have a –version arg)
/sw/bin/find (gnu version 4.2.20) and at
/sw/usr/local/find is gnu version 4.4.0
Here’s the rub:
if I run
find . -name “*.html” ! -path “./[a-z][a-z]/*” -ok aspell -x -c {} \;
(find links to /sw/bin/find) I don’t get the aspell interactive console. If I directly call /usr/bin/find (darwin’s find) I get the interactive console on each file found. Both versions of gnu find that I have show the same behavior. aspell touches these files, in fact, aspell backs them up (even with the -x switch — that’s another issue; parameters not passing) BUT they never go to the console for interactive review.
I’m guessing this is a simple user error — any ideas?
[...] I also placed a plea for help here. [...]
Hello Kyle,
Sorry for the delay. I did read your comment about the different version of find and behavior but I didn’t get a chance to try it on a Mac. I’m not a Mac user (except for job purpose) so I really don’t know why they didn’t behave the same way. Maybe you should ask a Mac Guru about this issue. The find version of BSD is not the same then the Linux find version for sure and may not behave the same…
You can also ask the author of that HowTo:
©2002–2006 by Wayne Pollock, Tampa Florida USA. All rights reserved.
From: http://www.hccfl.edu/pollock/Unix/FindCmd.htm
hi
r46cudfbhewdljfv
good luck
Hi,
Thanks for the detail.
I am looking for reverse of find command i.e. giving the directories which are not having a particular file.
I know we can do this by a script, but I just want to know whether we have such kind of commands or one line command which contains multiple like -exec/xargs.
Can we do find in the find command i.e. find . -type d \( -name “dirName” \) -exec find {} -name logFileName
thanks,
vijay gampa