Featured

9 Linux Shell Commands for Finding Files

Searching for files and patterns from the command line is a core skill for any Linux user, whether you’re a developer, sysadmin, or hobbyist.

 

Thankfully, the Linux ecosystem offers a wide range of tools—from classic commands like find and grep to powerful alternatives like ack, fzf, and erd—to help you locate, filter, and manage files efficiently. In this blog post, we walk you through the most essential search and filter commands in Linux. You’ll learn what they do, when to use them, and how to make the most of their options with real-world examples.

 

ack [options] search term

ack is a variant of grep optimized for programmers and administrators. Unlike the original, ack ignores GIT and SVN directories, backup files, and binary files. In many distributions, ack can be found in the package of the same name or in ack-grep. Alternatively, ack can also be installed as a Perl module (cpan App::Ack).

 

ack is compatible with grep, but searches all files in the current directory recursively by default (e.g., grep -r). The command is most frequently called in the forms ack search term or ack -i search term (not case-sensitive). A reference of ack-specific options is provided by ack --help and man ack.

 

An alternative to the ack variant is the ag command. Some distributions provide the command in the silversearcher-ag package. Alternatively, you can clone the program from GitHub and then compile it yourself:

 

https://github.com/ggreer/the_silver_searcher/wiki

 

The following example searches for files in /etc that contain the search term localhost and displays the corresponding hits together with the line numbers:

 

root# cd /etc

root# ack localhost

security/pam_env.conf

   52:# to "localhost" rather than not being set at all

   53:#REMOTEHOST DEFAULT=localhost OVERRIDE=@{PAM_RHOST

   64:#NNTPSERVER DEFAULT=localhost

speech-dispatcher/speechd.conf

   38:# for connections coming from localhost. If LocalhostAccessOnly is set

         to 0 it disables this

   199:#AudioNASServer "tcp/localhost:5450"

speech-dispatcher/modules/festival.conf

   7:#FestivalServerHost "localhost"

...

 

erd [options] files

erd from the erdtree package combines the functions of du, ls in a single command. The output is graphically appealing in colors (see the figure below). The command takes .gitignore into account and doesn’t display the files excluded there.

-.

Also displays hidden files.

-d line|word|block

Displays the size of files in lines, words, or blocks.

-H

Indicates the size of files in KiB, MiB, or GiB (instead of bytes).

-i

Ignores .gitignore; that is, it displays all files in a Git directory.

-l or --long

Displays access rights, owners, and groups.

-L or --level n

Tracks subdirectories only to the desired depth. By default, erd runs through all subdirectories.

-p or --pattern regex

Displays only files that match the regular pattern.

-s or --sort name|rname|size|rsize|access|raccess|mod|rmod

Sorts the output according to file name, file size, access, or modification time. The r variants reverse the sort order. Thus -s rsize displays the largest file first.

 

erd Provides an Overview of the /etc/systemd Directory

 

ind [path] [search options]

find helps you search for files. Various search criteria (pattern for the file name, file size, date of creation or last access, etc.) can be taken into account in the search. It’s even possible to apply further selection criteria to all files that meet these conditions using another program (e.g., grep). In this way, for example, all *.tex files that have been edited in the preceding three days and that contain the text “Graphics programming” could be found. Due to the large number of possible search criteria, man find provides a description of the command that is several pages long.

 

The following syntax description explicitly refers to the GNU find implementation commonly used on Linux. It’s characterized by some minor syntax differences compared to the find variants of other Unix systems: There, a path must be specified, while GNU find uses the current directory as the start directory. In addition, most find implementations require the use of the -print option to display the search results, which isn’t necessary with GNU find.

General Options

Unlike most other commands, find automatically searches all subdirectories. If this isn’t desired, the number of subdirectories must be limited via -maxdepth.

 

-depth

First processes the current directory and only then the subdirectories. Depending on

where you suspect the file you’re looking for is located, this procedure will lead to

initial results much more quickly.

 

-follow

Also edits directories that are captured by symbolic links.

 

-maxdepth n

Restricts the search to n directory levels. With -maxdepth 1, no subdirectories are taken into account at all.

Search Criteria

You can specify multiple search criteria at the same time. These criteria are logically linked by using AND. The search is aborted as soon as the first criterion isn’t met—the order of the criteria can therefore influence the speed of the command. Criteria can be grouped using \( and \), negated via !, and logically OR-linked using -o (see the examples).

 

-anewer reference file

Works like -newer (see that entry), but takes into account the time of the last read access.

 

-atime days or -cmin minutes

Takes into account the time of the last read access (access). The specification is in days or minutes (see -mtime).

 

-cnewer reference file

Works like -newer (see that entry), but takes into account the time of the last change to metadata.

 

-ctime days or -cmin minutes

Evaluates the time at which the metadata of the file (access rights, etc.) was last changed.

 

-executable

Finds files that are executable, that is, where the execute bit is set.

 

-group crime name or -nogroup group name

Finds files that belong to the specified group (or that don’t belong to it).

 

-mmin n

Works like mtime, but the time is given in minutes.

 

-mtime days or -mmin minutes

Finds files whose content was last modified exactly n days or minutes ago (modify). If a + is entered before the number, then all files older than n are captured. A preceding - returns files that are younger than n. -mtime 0 returns files that have been changed in the past 24 hours.

 

-name search pattern

Finds files that match the specified search pattern. If the search pattern contains wildcards, it must be placed in apostrophes. If you don’t want find to distinguish between uppercase and lowercase, you should use the -iname option instead of -name.

 

-newer reference file

Finds files that are newer than the reference file, that is, files that were created or modified after the reference file. For example, you can create a timestamp file at the start of a backup using touch. For an incremental further backup at a later point in time, only the files for which –newer timestamp applies are taken into account.

 

-path search pattern

Finds files that match the specified search pattern. The option goes beyond -name because the search pattern now affects not only the file name but also the path to it. This option is more flexible than the direct path specification in the first argument of find because here the wildcard characters also include the / character.

 

-perm access bits

Finds files whose access bits correspond exactly to the specified octal value (see chmod). If the octal value is preceded by a -, the file may also have access rights beyond this. If a / is placed in front, it’s sufficient if at least one of the searched access bits is set.

 

-size file size

Specifies the desired file size. The default specification is in multiples of 512. -size 3 therefore denotes files between 1,024 and 1,536 bytes. The additional c or k characters can be used to specify the size in bytes or KiB. A prefixed + includes all larger files, and a prefixed - includes all smaller files. -size +10k therefore returns all files that are larger than 10 KiB.

 

Note the somewhat unique logic of this command when using this option! find -size 1M considers files with a size between 1 byte and 1 MB. -size -1M only finds empty files. With -size +1M, you get files in the result that are larger than 1 MB.

 

-type character

Restricts the search to specific file types. The most important characters are f for regular files, d for directories, and l for symbolic links.

 

-user username or -nouser username

Finds files that belong to the specified user (or that don’t belong to them).

Actions When Finding a File

-exec command [options] {} \;

Calls the specified command and passes the file name of the file found that has fulfilled all the criteria processed so far. The command can then perform a test to check whether the file meets additional criteria. A typical program that is called by -exec is grep. Alternatively, you can also call commands here that move, copy, or otherwise process the files found.

 

{} is a placeholder for the file name. ; concludes the command call; that is, additional find options can be specified after it. \ is required within the shell to prevent the interpretation of ; as a special character.

 

-exec command [options] {} +

As in the preceding paragraphs, but the specified command isn’t called for every file found. Instead, find tries to pass as many results as possible to the command at once, which is much more efficient. The number of files is only limited by the maximum length of a command. This is approximately 2 million characters in current Linux distributions.

 

-ls

Provides detailed information on each file found (similar to ls -l).

 

-print

Displays the file names found on the screen. This option is the default setting unless -exec is used.

 

-print0

Separates the file names of the result list by 0 bytes. This enables further processing of file names with spaces via xargs.

 

▸ -printf format

Displays the file names found and other information on the screen. The format string can be used to specify the format of the output and the additional information that is also to be output (e.g., the file size or the date of the last change). The syntax for the format string is described in the man pages.

Examples

The first find command returns all files in the current directory (including hidden files, but no files from subdirectories); the second command only returns ordinary files (but no invisible files):

 

user$ find -maxdepth 1 -type f -name '*'

user$ find -maxdepth 1 -type f -name '[!.]*'

 

The following command searches the /etc directory for files that have been changed in the past two weeks. The command must be run with root permissions because some files in /etc may not be read by normal users:

 

root# sudo find /etc -mtime -14

 

The following command deletes all backup files that are identified by the ~ character at the end of the file name. find also takes all subdirectories into account. The list of files to be deleted is redirected to rm by the command substitution with $(command).

 

root# rm $(find . -name '*~')

 

If there is a large number of files, an error will occur when you run the preceding command: the command line with all *~ files will become so long that it exceeds the maximum command line length. In such cases, you must either use the -exec option of the find command or the xargs command. The xargs variant has the advantage that it can also cope with file names that contain spaces.

 

user$ find -name '*~.jpg' -exec rm {} \;

 

In the next example, all files in a directory are to be made readable for everyone (see chmod). It’s somewhat more difficult to use find to set the execute bit for all subdirectories (but not for ordinary files) so that everyone on the computer can use cd to change to the directories. The + sign at the end of the command means that chmod isn’t called for each directory individually, but that as many directories as possible are passed to chmod at once.

 

root# cd /directory/for/all

root# chmod -R a+r *

root# find . -type d -exec chmod a+x {} +

 

The last example first creates a reference file with the date 1/1/2025 and the directory ../new-images by using touch. All images from the local directory that have been created since 1/1/2025 are now copied there. new-images must not be created in the current directory; otherwise, find will also capture the files copied there. In addition, note the OR link for the file identifiers *.jpg and *.png.

 

user$ touch 2025 -t 202501010000

user$ mkdir ../new-images

user$ find . -newer 2025 \( -name \*.png -o -name \*.jpg \) \

   -exec cp {} ../new-images +;

 

Further find examples can be found in the description of the grep and xargs commands.

Alternatives

find is an important command, but it’s difficult to use because nobody can remember all the possible options. Accordingly, there are many attempts to create more convenient alternatives to find. Here are two of them:

  • erd combines the most important functions of du, find, ls, and tree in a single command.
  • fzf, on the other hand, excels with its interactive selection of files.

Another option is fd (see https://github.com/sharkdp/fd), which is very similar to find. Its biggest advantages are that the options are easier to memorize and the search results are displayed in color.

 

fzf [options]

fzf from the package of the same name stands for fuzzy finder and is a command for the interactive search and selection of files. If the command is started without any other options, it searches the current directory such as find . –type f for files and displays the result list. By entering a search pattern, you can filter the result interactively at lightning speed and then select a file or multiple files using the cursor keys or (Tab), respectively. (The multiple selection requires that fzf was started with the -m option.) (Enter) ends the command and displays the file names.

 

This basic function sounds rather unspectacular. The strength of fzf comes from its integration into the shell. Provided that fzf is installed correctly, fzf can also be triggered by typing ** (Tab), allowing the interactive completion of commands: Using emacs ** (Tab), you can open the previously selected file. With kill -9 ** (Tab), fzf provides processes for selection, and with ssh ** (Tab), it returns host names. (Ctrl) + (T) lists all files, (Ctrl) + (R) lists recently executed commands, and (Alt) + (C) changes to a subdirectory.

 

fzf has countless other keyboard shortcuts and functions that I can’t go into here for reasons of space. Instead, I recommend that you watch one of the many videos on fzf. Even though I’m not usually a video fan, in this case, it’s worth it!

 

fzf therefore doesn’t replace find in all its functions. But once you get used to the convenience of fzf, you’ll need find much less often.

 

grep [options] search pattern file and grep -R [options] search pattern

grep searches the specified text file for a search pattern and displays the text passages found or simply indicates where or in how many lines the pattern was found. grep can be combined with find to search all files matching certain conditions for texts.

-n

Displays not only the line with the text found but also the n immediately preceding and following lines (e.g., grep -3).

-c

Indicates only the number of lines in which the search pattern was found, but not the lines themselves.

--color=auto

Indicates the matches in color during output. This only works if you display the grep result directly in a console, but not if you process the result with another command (e.g., with sort or less). To embed the color information in the output in this case as well, you must use --color=always.

-E

Activates Extended Regular Expressions (EREs). This extended syntax allows the characters ? (not at all or once), + (at least once), and | (logical OR) in the search pattern. For example, grep -E 'pattern1|pattern2' file returns all lines of the specified file containing one of the two patterns.

-f file

Reads the options listed here for the specified file (for complex or frequently used search patterns).

-i

Doesn’t distinguish between uppercase and lowercase.

-l

Displays only the file names in which the search pattern was found.

-n

Also indicates the line number of each line in the output.

-o

Doesn’t output the entire line, but only the part of the line that matches the search pattern (only matching).

-P

Interprets the regular pattern according to the Perl Compatible Regular Expressions (PCRE2).

-q

Doesn’t provide any screen output and only returns the return value 0 (search text found) or 1 (not found). This option is useful if grep is called by other programs (see the example in find).

-R

Applies grep recursively to all files in the directory tree.

-v

Applies the inverse effect: grep returns all lines that do not match the search pattern. grep -v '^#' file | cat -s returns all lines of the file that don’t begin with # (where cat -s reduces several empty lines to a single one).

-w

Finds only entire words. If this option is specified, the search pattern “the” in the word “these” is no longer recognized.

 

The search pattern consists of two components: the specification of what is being searched for and the specification of how often the search expression may occur. The table below summarizes the meanings of the most important characters. The abbreviation ERE marks characters for the Extended Regular Expressions (-E option or egrep command).

 

Character Meaning
abc The character string abc.
[abc] One of the characters a, b, or c.
[^abc] None of the characters a, b, or c (i.e. any other character.
[a-z] One of the characters between a and z.
. Any character.
? The preceding character may not appear at all or may appear once (ERE).
* The character may appear any number of times (or not at all).
+ The character may appear any number of times, but must appear at least once (ERE).
{n} The character must appear exactly n times.

{,n}

The character may appear a maximum of n times.
{n,} The character must appear at least n times.
{n,m} The character must appear at least n times and not more than m times.
^ Start of line.
$ End of line.
| Logical OR (ERE).

 

If special characters such as ?, *, +, [, ], (, ), #, or ! will be used in the search pattern, they must be preceded by \. Patterns are already predefined for some character groups, such as [:digit:] for digits or [:space:] for white space (i.e., blank and tab characters; see man page).

 

Some examples of search patterns follow:

  • 'abc' searches for exactly this character string.
  • '[a-z][0-9]+' searches for strings starting with a lowercase letter and followed by one or more digits.
  • '\(.*\)' searches for any character strings that are enclosed in two parentheses.

grep only applies the search pattern line by line. Text passages that are interrupted by a line break can’t be recognized.

Examples

The following command searches the Apache logging file /var/log/apache2/access.log for all lines containing IP address 1.2.3.4. The command must be executed with root permissions because regular users don’t have access rights to the Apache logging files.

 

root# grep 1.2.3.4 /var/log/apache2/access.log

 

The following command determines how often the mysql string has been used in a PHP file in both uppercase and lowercase:

 

user$ grep -c -i mysql code.php

 

In the next example, all Apache configuration files are searched recursively starting from a start directory. grep displays the file names in which the ErrorDocument keyword appears:

 

root# cd /etc/apache2

root# grep -R -l ErrorDocument

 

The following grep command filters out all lines from the kernel messages that contain the search pattern eth in uppercase or lowercase:

 

root# dmesg | grep -i eth

e1000: eth0 NIC Link is Down

e1000: eth0 NIC Link is Up 1000 Mbps Full Duplex, Flow Control: RX ...

 

The output of the df command contains various entries for temporary file systems, which are often uninteresting. grep -v eliminates these lines. (df -x tmpfs will also lead to the desired result.)

 

root# df | grep -v tmpfs

File system              1K blocks  Used     Available  Used%   Mounted to

/dev/mapper/fedora-root  16080304   4820060  10420360   32%     /

/dev/sda1                487652     109669   348287     24%     /boot

 

Some configuration files in the /etc directory look as if the authors have confused the file with the manual. Hidden among hundreds, sometimes thousands, of lines of comments are a few settings that are actually effective. The following commands eliminate all lines that start with # or ; or that are empty:

 

root# cd /etc/samba

root# cp smb.conf smb.conf.orig

root# grep -Ev '^#|^;|^$' smb.conf.orig > smb.conf

 

To also eliminate comments where # or ; isn’t at the beginning of the line, as well as empty lines with white space (spaces, tab characters), you must formulate the grep command as follows:

 

root# grep -Ev '^[[:space:]]*#|^[[:space:]]*;|^[[:space:]]*$' \

   smb.conf.orig > smb.conf

 

The following example searches an Apache configuration file for lines containing the search pattern SSL*File:

 

user$ grep 'SSL.*File'   /etc/httpd/conf.d/ssl.conf

SSLCertificateFile       /etc/letsencrypt/live/pi-book.info/cert.pem

SSLCertificateKeyFile    /etc/letsencrypt/live/pi-book.info/privkey.pem

SSLCertificateChainFile  /etc/letsencrypt/live/pi-book.info/chain.pem

 

You can also combine find and grep to perform particularly effective searches. In the following command, find searches for *.php files, and grep checks whether they contain the mysql string. If they do, the respective file name will be displayed on the screen. Note that you must specify the -print option after -exec.

 

root# find -name '*.php' -exec grep -q -i mysql {} \; -print

Variants of grep

  • ack and ag are grep variants optimized for programmers. They ignore backup files, binary files, and directories of version management systems.
  • grepmail helps to search email archives in mbox format for character strings. The advantage over grep is that the entire email is extracted from the file rather than a single line.
  • zgrep searches compressed files.

 

locate pattern

locate enables a particularly fast search for files. It searches a file database, usually updated once a day, in which the specified pattern occurs in the full file name (including path). However, files that were created or changed after the last database update can’t be found.

 

In most cases, locate and the underlying updatedb system must be installed separately (mlocate package) and often also configured.

 

updatedb

updatedb creates an index directory for the locate command. The index contains a list of all files contained in the entire file system. The command is usually executed automatically once a day by a cron job. Its execution requires root permissions. Depending on the distribution, the file database is saved in the /var/lib, /var/lib/slocate, or /var/lib/mlocate directory.

 

whereis file

whereis searches all common paths for binary files, man files, and source code for the specified file name. whereis is therefore less thorough than find, but much faster. The man page for whereis lists the directories that are searched.

 

which command

which searches all paths specified in PATH for the command. which returns the full name of the command that would be executed if the command were called without path information. This is particularly useful if multiple versions of a command exist in different directories.

 

In bash, type can also be used instead of which. The type command helps you find out whether command is actually a built-in shell command, an alias, or a self-defined function.

Example

which determines where the ls command is stored in the file system:

 

user$ which ls

/usr/bin/ls

 

Conclusion

Mastering Linux search commands opens the door to faster troubleshooting, better file management, and more powerful automation. Whether you’re using grep to scan logs, find to locate and act on files, or turning to user-friendly tools like ack and fzf, each command in your toolbox makes you a more capable and confident user. Bookmark this post as a reference, and keep experimenting with different options and combinations to tailor your searches to any situation. With time, these tools will become second nature—and indispensable.

 

Editor’s note: This post has been adapted from a section of the book Linux Command Reference: Shell Commands from A to Z by Michael Kofler. Dr. Kofler is a programmer and Linux administrator. He studied electrical engineering/telematics at Graz University of Technology. He has been one of the most successful and versatile computing authors in the German-speaking world for many years. His current topics include Linux, Docker, Git, hacking and security, Raspberry Pi, and the programming languages Swift, JavaPython, and Kotlin. Dr. Kofler also teaches at the Joanneum University of Applied Sciences in Kapfenberg, Austria.

 

This post was originally published 7/2025.

Recommendation

Linux Command Reference
Linux Command Reference

Linux users, your go-to desktop reference is here! Find practical commands for the Linux tasks you perform, from managing files to working with graphics systems to programming with Bash. Commands are grouped by topic and listed alphabetically to help you quickly find what you’re looking for, and options are listed for each entry to help you modify your commands. With detailed descriptions and practical examples, this guide doesn’t just tell you which commands to use—it shows you how to use them, too!

Learn More
Rheinwerk Computing
by Rheinwerk Computing

Rheinwerk Computing is an imprint of Rheinwerk Publishing and publishes books by leading experts in the fields of programming, administration, security, analytics, and more.

Comments