Page Body

Searching for File System Objects With find and locate

Two popular commands used to find file system objects are find and locate.

Note: If you are not familiar with the GNU/Linux command line interface, review the Conventions page before proceeding.

find

The find command syntax is:

find example_options example_directory_tree_to_search example_search_expression

Some of find's options include:

-P
Never follow symbolic links; this is the default behavior for find
-L
Follow symbolic links
-H
Do not follow symbolic links, except while processing command line arguments; the information about the link itself is used as a fallback if the object pointed to by the symbolic link cannot be examined

You can provide find with a space-separated list of directory trees to search, as well.

By default, find is recursive, outputs hidden objects, and includes the -print action, which prints the name of each found object on the standard output, followed by a newline.

If example_directory_tree_to_search is an absolute path name, find will return absolute path names. If example_directory_tree_to_search is a relative path name, find will return relative path names.

Expressions

The part of the command after the list of starting point(s) (i.e., example_directory_tree_to_search) is the expression (i.e., example_search_expression). This expression is a query specification that describes how to match file system objects and what to do with the items that are matched.

A find expression is composed of:

  • Actions Actions have side effects and return either true or false, usually based on whether or not they are successful.
  • Global Options Global options affect the operation of actions and tests specified on any part of the command line. Global options always return true.
  • Operators Operators join together the other items within the expression.
  • Positional Options Positional options affect only actions and tests that follow them. Positional options always return true.
  • Tests Tests return a true or false value, usually on the basis of some property of an object that is being considered.

There are many potential values for each of the items listed above, but the following are some of the most useful ones.

Actions

-delete
Delete files; true if removal succeeded; if the removal failed, an error message is issued
-exec
Execute a command provided to the action as an argument; true if exit status 0 is returned; all following arguments to find are taken to be arguments to the command until a \; is encountered; the string '{}' is replaced by the current object name being processed
-ls
true; list current object in ls -dils format on the standard output
-ok
Like the -exec action, but prompts the user first; if the user agrees (y), the command is run; otherwise (n), returns false; this is a good way to test the results before executing a potentially dangerous command
-print
true; print the full object name on the standard output, followed by a newline; this is the default behavior of find
-print0
true; print the full object name on the standard output, followed by a null character; this allows object names that contain newlines or other types of white space to be correctly interpreted by programs that process find output

Global Options

-help
Print a summary of the command line usage of find, and then exit
-maxdepth
Descend at most example_non_negative_integer levels of directories below the command line arguments; example_non_negative_integer is provided to this option as an argument; -maxdepth 0 means only apply the tests and actions to the starting point(s) themselves
-xdev
Do not descend directories on other file systems

Operators

!
The logical NOT (e.g., ! example_expression)
-a
The logical AND (e.g., example_expression_1 -a example_expression_2 )
-o
The logical OR (e.g., example_expression_1 -o example_expression_2)

It is best to enclose your find operator expressions in escaped parentheses (e.g., \( example_expression_1 -a example_expression_2 \)).

If you do not specify an operator, -a is assumed.

Positional Options

-daystart
Measure times from the beginning of today, rather than from 24 hours ago (for -amin, -atime, -cmin, -ctime, -mmin, and -mtime tests)
-regextype
Changes the regular expression syntax understood by the -regex and -iregex tests that occur later on the command line; you must pass this option a type as an argument; valid types are findutils-default, awk, egrep, ed, emacs, gnu-awk, grep, posix-awk, posix-basic, posix-egrep, posix-extended, posix-minimal-basic, and sed
-warn, -nowarn
Turn warning messages on or off, respectively

Tests

-atime
Specify object access time; this test takes a number as an argument in the format of example_number for the exact number, +example_number for greater than the number, or -example_number for less than the number
-ctime
Specify object change time; this test takes a number as an argument in the format of example_number for the exact number, +example_number for greater than the number, or -example_number for less than the number
-group
Specify a group owner; this test takes either a group name or a group ID (GID) as an argument
-iname
Specify a case-insensitive object name pattern; this test takes a string as an argument
-inum
Specify inode number; this test takes an inode number as an argument
-iregex
Like -regex, but the match is case insensitive
-links
Specify reference count (i.e., hard link count); this test takes a reference count number as an argument
-mtime
Specify object modification time; this test takes a number as an argument in the format of example_number for the exact number, +example_number for greater than the number, or -example_number for less than the number
-name
Specify an object name pattern; this test takes a string as an argument
-perm
Specify permissions set; matches the exact mode provided to the test as an argument
-regex
Object path name matches regular expression provided as an argument to the test
-size
Specify an object size (default 512 byte-blocks); this test takes a number as an argument in the format of example_number for the exact number, +example_number for greater than the number, or -example_number for less than the number; example_number can be bytes (c), kibibytes (k), mebibytes (M), and gibibytes (G)
-type
Specify object type; this test takes an object type as an argument; accepted types include block (b), character (c), directory (d), regular file (f), symbolic link (l), named pipe (p), and socket (s)
-user
Specify a user owner; this test takes either a user name or a user ID (UID) as an argument

Examples

More than most commands, examples help illustrate how the find command works.

Find All Objects With the Object Name foo.txt

$ find '/home/amnesia' -name 'foo.txt'
/home/amnesia/foobar/foo.txt
/home/amnesia/Documents/foobar/foo.txt
/home/amnesia/foo.txt

Find All Objects With an Object Name That Starts With foo

Adding search patterns to your expression can make find more flexible.

$ find '/home/amnesia' -name 'foo*'
/home/amnesia/foo_4.txt
/home/amnesia/foo_3.txt
/home/amnesia/foobar
/home/amnesia/foobar/foo_2.txt
/home/amnesia/foobar/foo.txt
/home/amnesia/foo_1.txt
/home/amnesia/foo_2.txt
/home/amnesia/Documents/foobar
/home/amnesia/Documents/foobar/foo_2.txt
/home/amnesia/Documents/foobar/foo.txt
/home/amnesia/foo.txt
/home/amnesia/foo_5.txt

Find All Directories With a Name That Starts With foo

$ find '/home/amnesia' -type d -name 'foo*'
/home/amnesia/foobar
/home/amnesia/Documents/foobar

Find All Directories With a Name That Starts With Either D or P

$ find '/home/amnesia' -type d \( -name 'D*' -o -name 'P*' \)
/home/amnesia/Pictures
/home/amnesia/Documents
/home/amnesia/Public
/home/amnesia/Downloads
/home/amnesia/Desktop

Find All Objects Accessed Two Days Ago

$ find '/home/amnesia' -atime 2
/home/amnesia/.cache/event-sound-cache.tdb.7bf962cd8dcd427f95d5b537cddf5e72.x86_64-pc-linux-gnu

Find All Objects Modified More Than Two Days Ago

$ find '/home/amnesia' -mtime +2
/home/amnesia/.cache/flatpak
/home/amnesia/.cache/flatpak/system-cache
/home/amnesia/foo_5.txt

Find All Objects Changed Less Than Two Days Ago

$ find '/home/amnesia' -ctime -2
/home/amnesia/.cache/tracker/meta.db
/home/amnesia/.cache/tracker/meta.db-wal
/home/amnesia/.cache/tracker/locale-for-miner-apps.txt
/home/amnesia/.cache/gnome-software/shell-extensions
/home/amnesia/.cache/gnome-software/shell-extensions/gnome.json

Find All Objects Owned By amnesia User

$ find '/home/amnesia' -user 'amnesia' | head
/home/amnesia
/home/amnesia/.ssh
/home/amnesia/Videos
/home/amnesia/Pictures
/home/amnesia/Music
/home/amnesia/Documents
/home/amnesia/Public
/home/amnesia/Templates
/home/amnesia/Downloads
/home/amnesia/.ICEauthority

Above, the output of the find command is piped into the head command, so that we only see the first ten lines of command output.

Find All Objects Less Than One Gibibyte in Size

$ find '/home/amnesia' -size -1G
/home/amnesia/.local/share/tracker/data/.meta.isrunning
/home/amnesia/.local/share/gnome-settings-daemon/input-sources-converted
/home/amnesia/.local/share/gnome-shell/gnome-overrides-migrated
/home/amnesia/.gnupg/S.gpg-agent.ssh
/home/amnesia/.gnupg/S.gpg-agent.browser
/home/amnesia/.gnupg/S.gpg-agent.extra
/home/amnesia/.gnupg/S.gpg-agent
/home/amnesia/.gnome2_private/.placeholder
/home/amnesia/.gnome2/accels/.placeholder

Find All Files Named Foo.txt or foo.txt and Remove Them

find '/home/amnesia' -type f -iname 'foo.txt' -exec rm -f '{}' \;

-exec starts a new process for every file system object found by find. This can be inefficient, and you can address this by using the xargs command.

For example, you can redo the command above as such:

find '/home/amnesia' -print0 -type f -iname 'foo.txt' | xargs -0 -n1 -r rm -f

xargs (Execute as Arguments) takes the file system objects found by the find command and passes them to rm as arguments. xargs can have problems with object names that contain spaces or newlines, but you can get around this by telling find and xargs to use null bytes instead of newlines. -print0 tells find to use null bytes to separate its results, instead of newlines. -0 helps xargs understand this kind of input.

-n1 tells xargs to use, at max, one argument per command line, and -r (short for --no-run-if-empty) makes sure xargs only runs if it receives input from find.

locate

The locate command can also be used to find file system objects, but it differs from the find command in several ways. locate's basic syntax is:

locate example_string

locate may not be installed on your GNU/Linux distribution, but it is most likely in your distribution's repository. For example, you can install locate on Debian by running the following command:

# apt install locate

By default, the locate command does not search your file system in real-time, like find does. Instead, it searches a previously constructed database of file system objects. Usually, this makes running locate queries faster than running find queries. However, you may get positive results for an object that no longer exists (i.e., the object was removed from the file system before the database that locate uses was updated).

locate does not have the manifold search filters that find does. It simply searches object path names for the string that you specify. Unlike find, locate interprets strings you specify, without any special shell characters required, as a search pattern (e.g., the string Documents will automatically be treated by locate as *Documents*). Also, locate will search for your pattern anywhere in an object's pathname.

For example, a search for Do can return these types of results:

$ locate 'Do'
/home/amnesia/Documents
/home/amnesia/Documents/foobar
/home/amnesia/Documents/foobar/bar.txt
/home/amnesia/Documents/foobar/foo_2.txt
/home/amnesia/Downloads
/usr/include/X11/bitmaps/Down
/usr/include/llvm-7/llvm/Analysis/DomPrinter.h
/usr/lib/libreoffice/program/wizards/ui/DocumentPreview.py
/usr/lib/libreoffice/share/gallery/arrows/A43-TrendArrow-Green-GoDown.svg
/usr/lib/libreoffice/share/gallery/arrows/A66-Arrow-Green-Down.svg

However, you can specify your own search patterns to make locate more selective in its behavior:

$ locate /home/amnesia/Do*
/home/amnesia/Documents
/home/amnesia/Documents/foobar
/home/amnesia/Documents/foobar/bar.txt
/home/amnesia/Documents/foobar/foo_2.txt
/home/amnesia/Downloads

As you can see, locate returns the absolute pathnames for objects that match your query.

To have locate run in real-time on the existing file system (versus searching its cached database), you can use the -e option. Keep in mind, this negates locate's speed advantage over find.

You can force an update of locate's database with the updatedb command. However, most GNU/Linux distributions invoke updatedb via a script that is usually tied to a cron job.

For example, on Debian, you can invoke updatedb by running the following command:

# /etc/cron.daily/locate

Running updatedb in this manner ensures that it uses the same parameters as it was originally configured to use.

Documentation

You can learn more about find and locate by examining their man pages at the command prompt (man find and man locate) or online.

Avatar

Enjoyed this post?

Subscribe to the feed for the latest updates.