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 ex_options ex_directory_tree_to_search... ex_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 ex_directory_tree_to_search is an absolute path name, find will return absolute path names. If ex_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., ex_directory_tree_to_search) is the expression (i.e., ex_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 ex_command
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 ex_command
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 ex_depth
Descend at most ex_depth levels of directories below the command line arguments. ex_depth is a non-negative integer. -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., ! ex_expression).
-a
The logical AND (e.g., ex_expression_1 -a ex_expression_2 ).
-o
The logical OR (e.g., ex_expression_1 -o ex_expression_2).

It is best to enclose your find operator expressions in escaped parentheses (e.g., \( ex_expression_1 -a ex_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 ex_reg_ex_type
Changes the regular expression syntax understood by the -regex and -iregex tests that occur later on the command line. ex_reg_ex_type can be 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 ex_time
Specify object access time. ex_time can be an exact number, +ex_time for greater than the number, or -ex_time for less than the number.
-ctime ex_time
Specify object change time. ex_time can be an exact number, +ex_time for greater than the number, or -ex_time for less than the number.
-group ex_group
Specify a group owner. ex_group can be either a group name or a group ID (GID).
-iname ex_pattern
Specify a case-insensitive object name pattern.
-inum ex_inode_number
Specify inode number.
-iregex ex_reg_ex
Like -regex, but the match is case insensitive.
-links ex_reference_count
Specify reference count (i.e., hard link count).
-mtime ex_time
Specify object modification time. ex_time can be an exact number, +ex_time for greater than the number, or -ex_time for less than the number.
-name ex_pattern
Specify an object name pattern.
-perm ex_permissions_set
Specify permissions set. Matches the exact mode.
-regex ex_reg_ex
Object path name matches regular expression.
-size ex_size
Specify an object size (default 512 byte-blocks). ex_size can be the exact number, +ex_size for greater than the number, or -ex_size for less than the number. ex_size can be in bytes (c), kibibytes (k), mebibytes (M), and gibibytes (G).
-type ex_type
Specify object type. Accepted types include block (b), character (c), directory (d), regular file (f), symbolic link (l), named pipe (p), and socket (s).
-user ex_user
Specify a user owner. ex_user can be a user name or a user ID (UID).

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 ex_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 your specified string, 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.