Find is a very powerful, but complicated command. You can do any of the following things with find:
- Search on a filename
- Search on permissions (both user and group)
- Search on ownership
- Search on file type
- Search on file size
- Search on timestamps (created, last-modified, last-accessed)
- Search only in certain directories
It would take a full chapter to explain all of the functionality in the find command. We will only be describing the most common use cases. The real lesson here is being aware of the advanced functionalities of find; if you ever need to look for files with a specific set of attributes, always think of the find command first and check out the man file page to see if you can utilize find for your search (spoiler alert: this is almost always the case!).
Let's start with the basic use of find: find <location> <options and arguments>. Without any options and arguments, find will print every file it finds within the location:
reader@ubuntu:~$ find /home/reader/
/home/reader/
/home/reader/.gnupg
/home/reader/.gnupg/private-keys-v1.d
/home/reader/.bash_logout
/home/reader/.sudo_as_admin_successful
/home/reader/.profile
/home/reader/.bashrc
/home/reader/.viminfo
/home/reader/.lesshst
/home/reader/.local
/home/reader/.local/share
/home/reader/.local/share/nano
/home/reader/.cache
/home/reader/.cache/motd.legal-displayed
/home/reader/.bash_history
reader@ubuntu:~$
You might have been under the impression that your home directory was empty. It actually contains quite a number of hidden files or directories (which start with a dot), which find has found for us. Now, let's apply a filter with the -name option:
reader@ubuntu:~$ find /home/reader/ -name bash
reader@ubuntu:~$ find /home/reader/ -name *bash*
/home/reader/.bash_logout
/home/reader/.bashrc
/home/reader/.bash_history
reader@ubuntu:~$ find /home/reader/ -name .bashrc
/home/reader/.bashrc
reader@ubuntu:~$
Contrary to what you might have expected, find works differently from locate with regards to partly matched files. Unless you add wildcards around the argument to -name, it will only match on the full filename, not on partly matched files. This is definitely something to keep in mind. Now, what about looking only for files, instead of directories as well? For this, we can use the -type option with the d argument for directories or f for files:
reader@ubuntu:~$ find /home/reader/ -type d
/home/reader/
/home/reader/.gnupg
/home/reader/.gnupg/private-keys-v1.d
/home/reader/.local
/home/reader/.local/share
/home/reader/.local/share/nano
/home/reader/.cache
reader@ubuntu:~$ find /home/reader/ -type f
/home/reader/.bash_logout
/home/reader/.sudo_as_admin_successful
/home/reader/.profile
/home/reader/.bashrc
/home/reader/.viminfo
/home/reader/.lesshst
/home/reader/.cache/motd.legal-displayed
/home/reader/.bash_history
reader@ubuntu:~$
The first result presents all directories within /home/reader/ (including /home/reader/!), while the second result prints all files. As you can see, there is no overlap, since a file under Linux is always of only one type. We can also combine multiple options, such as -name and -type:
reader@ubuntu:~$ find /home/reader/ -name *cache* -type f
reader@ubuntu:~$ find /home/reader/ -name *cache* -type d
/home/reader/.cache
reader@ubuntu:~$
We start by looking for files in /home/reader/ which contain the string cache. The find command does not print anything, which means we did not find anything. If we look for directories with the cache string, however, we are shown the /home/reader/.cache/ directory.
As a last example, let's look at how we can use find to distinguish between files of different sizes. To do this, we'll create an empty file using touch and a non-empty file using vim (or nano):
reader@ubuntu:~$ ls -l
total 0
reader@ubuntu:~$ touch emptyfile
reader@ubuntu:~$ vim textfile.txt
reader@ubuntu:~$ ls -l
total 4
-rw-rw-r-- 1 reader reader 0 Aug 19 11:54 emptyfile
-rw-rw-r-- 1 reader reader 23 Aug 19 11:54 textfile.txt
reader@ubuntu:~
As you can see from the 0 and 23 on-screen, emptyfile contains 0 bytes, whereas textfile.txt contains 23 bytes (which, not entirely coincidental, contains a sentence of 23 characters). Let's see how we can use the find command to find both files:
reader@ubuntu:~$ find /home/reader/ -size 0c
/home/reader/.sudo_as_admin_successful
/home/reader/.cache/motd.legal-displayed
/home/reader/emptyfile
reader@ubuntu:~$ find /home/reader/ -size 23c
/home/reader/textfile.txt
reader@ubuntu:~$
To do this, we use the -size option. We give it the number we're looking for, followed by a letter which indicates which range we're dealing with. c is used for bytes, k for kilobytes, M for megabytes, and so on. You can find these values on the manual page. As the results show, there are three files which are exactly 0 bytes: our emptyfile is one of them. These is one file which is exactly 23 bytes: our textfile.txt. You might think: 23 bytes, that's very specific! How will we ever know how many bytes a file is exactly? Well, you won't. The creators of find have also implemented a greater than and lower than construct, which we can use to give us a little more flexibility:
reader@ubuntu:~$ find /home/reader/ -size +10c
/home/reader/
/home/reader/.gnupg
/home/reader/.gnupg/private-keys-v1.d
/home/reader/.bash_logout
/home/reader/.profile
/home/reader/.bashrc
/home/reader/.viminfo
/home/reader/.lesshst
/home/reader/textfile.txt
/home/reader/.local
/home/reader/.local/share
/home/reader/.local/share/nano
/home/reader/.cache
/home/reader/.bash_history
reader@ubuntu:~$ find /home/reader/ -size +10c -size -30c
/home/reader/textfile.txt
reader@ubuntu:~$
Let's say we're looking for a file that's at least larger than 10 bytes. We use the + option on the argument, which only prints the files that are larger than 10 bytes. However, we still see too many files. Now, we expect the file to also be smaller than 30 bytes. We add another -size option, this time specifying -30c, meaning that the file will be less than 30 bytes. And, not entirely unexpectedly, our 23 byte testfile.txt is found!
All of the preceding options and more can be combined to form a very powerful search query. Are you looking for a file, which is at least 100 KB but not more than 10 MB, located somewhere in /var/, that was created in the last week, and is readable to you? Just combine the options in find and you will definitely find that file in no time!