In Unix-like operating systems, a file is more than just a named space on a disk. It is a universal interface for accessing information. A Linux user should know how to quickly find the necessary files by name and other criteria.
The first file search command in Linux that we will look at is called locate
. It performs a fast search by name in a special database and outputs all names matching the specified substring.
Suppose we want to find all programs that begin with zip
. Since we are looking specifically for programs, it is logical to assume that the directory name ends with bin
. Taking this into account, let’s try to find the necessary files:
locate bin/zip
Output:
locate
performed a search in the pathname database and displayed all names containing the substring bin/zip
.
For more complex search criteria, locate
can be combined with other programs, for example, grep
:
locate bin | grep zip
Output:
Sometimes, in Linux, searching for a file name with locate
works incorrectly (it may output names of deleted files or fail to include newly created ones). In such a case, you need to update the database of indexes:
sudo updatedb
locate
supports wildcards and regular expressions. If the string contains metacharacters, you pass a pattern instead of a substring as an argument, and the command matches it against the full pathname.
Let’s say we need to find all names with the suffix .png
in the Pictures directory:
locate '*Pictures/*.png'
Output:
To search using a regular expression, the -r
option is used (POSIX BRE standard):
locate -r 'bin/\(bz\|gz\|zip\)'
find
is the main tool for searching files in Linux through the terminal. Unlike locate
, find
allows you to search files by many parameters, such as size, creation date, permissions, etc.
In the simplest use case, we pass the directory name as an argument and find
searches for files in this directory and all of its subdirectories. If you don’t specify any options, the command outputs a list of all files.
For example, to get all names in the home directory, you can use:
find ~
The output will be very large because find will print all names in the directory and its subdirectories.
To make the search more specific, use options to set criteria.
Suppose we want to output only directories. For this, we will use the -type
option:
find ~/playground/ -type d
Output:
This command displayed all subdirectories in the ~/playground
directory. Supported types are:
b
— block devicec
— character deviced
— directoryf
— regular filel
— symbolic linkWe can also search by size and name. For example, let’s try to find regular files matching the pattern .png
and larger than one kilobyte:
find ~ -type f -name "*.png" -size +1k
Output:
The -name
option specifies the name. In this example, we use a wildcard pattern, so it is enclosed in quotes. The -size
parameter restricts the search by size. A +
sign before the number means we are looking for files larger than the given size, a -
sign means smaller. If no sign is present, find will display only files exactly matching the size.
Symbols for size units:
b
— 512-byte blocks (default if no unit is specified)c
— bytesw
— 2-byte wordsk
— kilobytesM
— megabytesG
— gigabytesfind
supports a huge number of checks that allow searching by various criteria. You can check them all in the documentation.
Operators help describe logical relationships between checks more precisely.
Suppose we need to detect insecure permissions. To do this, we want to output all files with permissions not equal to 0600 and all directories with permissions not equal to 0700. find
provides special logical operators to combine such checks:
find ~ \( -type f -not -perm 0600 \) -or \( -type d -not -perm 0700 \)
Supported logical operators:
-and
/ -a
— logical AND. If no operators are specified between checks, AND is assumed by default.-or
/ -o
— logical OR.-not
/ !
— logical NOT.( )
— allows grouping checks and operators to create complex expressions. Must be escaped.We can combine file search with performing actions on the found files. There are predefined and user-defined actions. For the former, find
provides the following options:
-delete
— delete found files-ls
— equivalent to ls -dils
-print
— output the full file name (default action)-quit
— stop after the first matchSuppose we need to delete all files with the .bak
suffix. Of course, we could immediately use find
with the -delete
option, but for safety it’s better to first output the list of files to be deleted, and then remove them:
find ~ -type f -name '*.bak' -print
Output:
After verification, delete them:
find ~ -type f -name '*.bak' -delete
With user-defined actions, we can combine the search with using various Linux utilities:
-exec command '{}' ';'
Here, command
is the command name, {}
is the symbolic representation of the current pathname, and ;
is the command separator. For example, we can apply the ls -l
command to each found file:
find ~ -type f -name 'foo*' -exec ls -l '{}' ';'
Output:
Sometimes commands can take multiple arguments at once, for example, rm
. To avoid applying the command separately to each found name, put a +
at the end of -exec
instead of a separator:
find ~ -type f -name 'foo*' -exec ls -l '{}' +
Output:
A similar task can be done using the xargs
utility. It takes a list of arguments as input and forms commands based on them. For example, here’s a well-known command for outputting files that contain “uncomfortable” characters in their names (spaces, line breaks, etc.):
find ~ -iname '*.jpg' -print0 | xargs --null ls -l
The -print0
argument forces found names to be separated by the null character (the only character forbidden in file names). The --null
option in xargs
indicates that the input is a list of arguments separated by the null character.
In Linux, searching for a file by name is done using the locate
and find
commands. Of course, you can also use file managers with a familiar graphical interface for these purposes. However, the utilities we have considered help make the search process more flexible and efficient.