You are using your Linux machine, you remember that somewhere you have some files you need…but how can you find your files using the Linux terminal?
The Linux find command is the most common command used to find files using the Linux command line. It allows to find files anywhere on the filesystem and it provides many options to define criteria for your search. The search could be based on filename, timestamp, file extensions, and a lot more.
In this guide you will learn how to use the Linux find command and you will also get ideas if you want to use find as part of your Bash scripts.
Let’s start!
Find Files Anywhere on Linux
First of all we will use the find command to see the structure of a directory, including subdirectories and files. I have created the following directories in the current directory:
ls -al
total 0
drwxr-xr-x 6 ec2-user ec2-user 53 Feb 11 21:09 .
drwxr-xr-x 5 root root 39 Feb 10 03:45 ..
drwxrwxr-x 2 ec2-user ec2-user 40 Feb 11 21:10 cfn
drwxrwxr-x 2 ec2-user ec2-user 42 Feb 11 21:10 core
drwxrwxr-x 2 ec2-user ec2-user 32 Feb 11 21:10 hosts
drwxrwxr-x 2 ec2-user ec2-user 36 Feb 11 21:10 log
As you can see the ls -al command shows all the directories I have created. But how can I see any subdirectories or files?
I can simply use the following command where the dot refers to the current directory:
find .
.
./log
./log/std_log
./log/err_log
./core
./core/core_file1
./core/core_file2
./core/dist
./core/dist/dist1
./core/dist/dist2
./cfn
./cfn/cfn_file1
./cfn/cfn_file2
./hosts
./hosts/host1
./hosts/host2
So the find command followed by a dot shows all the subdirectories and files in the current directory.
Now let’s see how can I find where the file dist1 is located:
find . -name dist1
./core/dist/dist1
The find command is followed by the directory in which I’m looking for the file (in this case the current directory) and by the name of the file I’m searching.
The -name flag allows to specify the name of the file we are looking for. Wildcards can also be used to match multiple files and directories.
If I want to find all the files and directories whose name starts with dist I can use a wildcard (*):
find . -name dist*
./core/dist
./core/dist/dist1
./core/dist/dist2
Searching For Files or Directories
Look at the last command we have executed.
What if I only want to find either files or directories that match the name dist?
To look for files we can use the -type flag followed by the letter f:
[myuser@localhost]$ find . -type f -name dist*
./core/dist/dist1
./core/dist/dist2
To look for directories we can use the -type flag followed by the letter d:
[myuser@localhost]$ find . -type d -name dist*
./core/dist
You can also pass the value l to the -type flag to search for symbolic links.
[myuser@localhost]$ find /dev -type l -name s*
/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi-disk-1
/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi-disk-0
/dev/stderr
/dev/stdout
/dev/stdin
And the ls command confirms that /dev/stderr is a symlink:
[myuser@localhost]$ ls -al /dev/stderr
lrwxrwxrwx. 1 root root 15 May 5 09:54 /dev/stderr -> /proc/self/fd/2
How to Find Files with a Specific Extension
A common scenario is to look for files that have a specific extension.
You might not be using the extension of a file in Linux as often as in Windows but there are cases when being able to find all the files with an extension can help.
For instance, let’s say I want to identify all the files with extension .log in the filesystem because I’m trying to troubleshoot a problem on my Linux system (it could be an operating system issue or an application issue).
To search for files with extension .log under the /var/log/ directory, I can use the following command:
find /var/log -name *.log
And this is the output I get:
find: ‘/var/log/httpd’: Permission denied
find: ‘/var/log/private’: Permission denied
/var/log/dnf.log
find: ‘/var/log/audit’: Permission denied
/var/log/tuned/tuned.log
/var/log/dnf.rpm.log
/var/log/dnf.librepo.log
/var/log/hawkey.log
find: ‘/var/log/sssd’: Permission denied
/var/log/boot.log
/var/log/anaconda/ks-script-7kh8_rxp.log
/var/log/anaconda/ifcfg.log
/var/log/anaconda/ks-script-yn6jstdm.log
/var/log/anaconda/dbus.log
/var/log/anaconda/packaging.log
/var/log/anaconda/program.log
/var/log/anaconda/dnf.librepo.log
/var/log/anaconda/hawkey.log
/var/log/anaconda/anaconda.log
/var/log/anaconda/ks-script-2vd1nbn1.log
/var/log/anaconda/storage.log
/var/log/anaconda/journal.log
I can see some files with .log extension in the output but I also receive “Permission denied” errors due to the fact that I don’t have permissions to access some directories under /var/log.
So, if you see the same error make sure you run the find command with a user that has access to that part of the filesystem.
Let’s say I want to find files with .log extension but also that have a name that starts with the letter a. I can do the following:
[myuser@localhost]$ find /var/log/ -name a*.log
/var/log/audit/audit.log
/var/log/anaconda/anaconda.log
Makes sense?
Find File and Directories Based on Modified Time or Date
One common scenario is to look for files based on their modified time.
This is, for example, useful if we want to identify log files generated by an application before a certain date.
Let’s say we are looking for files modified more than 7 days ago.
We can use the -mtime flag followed by a number n
that allows to filter files whose data was last modified n*24 hours ago (so n days ago).
For example let’s see how we can see files:
- In the /var/log/ directory
- Whose name matches the pattern “messages*”
- that have been modified more than 25 days ago:
[myuser@localhost]$ ls -ltr /var/log/messages*
-rw-------. 1 root root 237219 Jun 21 03:36 /var/log/messages-20200621
-rw-------. 1 root root 237142 Jun 28 03:44 /var/log/messages-20200628
-rw-------. 1 root root 236914 Jul 5 03:49 /var/log/messages-20200705
-rw-------. 1 root root 294417 Jul 12 03:50 /var/log/messages-20200712
-rw-------. 1 root root 271743 Jul 18 18:40 /var/log/messages
[myuser@localhost]$ find /var/log/ -name "messages*" -type f
/var/log/messages-20200628
/var/log/messages-20200705
/var/log/messages-20200712
/var/log/messages-20200621
/var/log/messages
[myuser@localhost]$ find /var/log/ -name "messages*" -type f -mtime +25
/var/log/messages-20200621
What if you want to find files modified less than 25 days ago?
You can use the following command:
[myuser@localhost]$ find /var/log/ -name "messages*" -type f -mtime -25
/var/log/messages-20200628
/var/log/messages-20200705
/var/log/messages-20200712
/var/log/messages
Notice how the difference between the first and the second find command is the + or – before 25.
Find Files in Linux By Size
Another common requirement is being able to find files bigger than a certain size.
Let’s apply this to the messages files in /var/log/ we have seen in the previous example:
ls -ltrh messages*
-rw------- 1 root root 1.2M Dec 22 03:28 messages-20191222
-rw------- 1 root root 1.2M Dec 29 03:15 messages-20191229
-rw------- 1 root root 1019K Jan 12 21:05 messages-20200112
-rw------- 1 root root 93K Feb 10 03:21 messages-20200210
-rw------- 1 root root 317K Feb 11 23:56 messages
We want to find the files bigger than 1MB and to do that we will use the -size flag followed by +1M:
find /var/log/ -name "messages*" -type f -size +1M
/var/log/messages-20191222
/var/log/messages-20191229
But how can we confirm that those two files are bigger then 1M without looking at the ls -ltrh output above and only using the find command?
We will find this out in the next section….
Executing Linux Commands With Find
Let’s say with the previous command we also want to see the size of each file.
We can use the -exec flag that allows to execute a specific command against each file returned by the find command.
So in this case we can use the ls -alh command as part of the find command, after the -exec flag:
find /var/log/ -name "messages*" -type f -size +1M -exec ls -alh {} \;
-rw------- 1 root root 1.2M Dec 22 03:28 /var/log/messages-20191222
-rw------- 1 root root 1.2M Dec 29 03:15 /var/log/messages-20191229
What does {} \; mean?
From experience this is not one of the easiest commands to remember, you will remember it with practice.
The string {} is replaced by the current file name being processed and the command is terminated with a semicolon that needs to be escaped to make sure it’s not interpreted by the shell.
The -exec flag is often used with the rm command and the -mtime flag to delete files older than a certain number of days when a scheduled cleanup job is executed (let’s say daily).
The command will be something like this, e.g. if we want to delete files modified more than 30 days ago under the directory /opt/demo/app/logs/
find /opt/demo/app/logs/ -type f -mtime +30 -exec rm -f {} \;
Conclusion
In this article you have learned how to use the find command to search for files and directories in Linux based on their name.
You have also learned how to filter results based on file extension, modified time and file size.
And finally you have see how the -exec flag can be extremely handy when it comes to executing a specific command against a large number of files identified by find based on a set of criteria that you can decide according to your requirements.
And the find command can be very powerful when you use it as part of a Bash script.
If you want to know another must-know command to manage files in Linux have a look at this Linux tutorial.
Claudio Sabato is an IT expert with over 15 years of professional experience in Python programming, Linux Systems Administration, Bash programming, and IT Systems Design. He is a professional certified by the Linux Professional Institute.
With a Master’s degree in Computer Science, he has a strong foundation in Software Engineering and a passion for robotics with Raspberry Pi.
Great content! Super high-quality! Keep it up! 🙂