How To Find Files In Linux

By Adam McQuistan in Linux  04/22/2020 Comment

Introduction

In this How To article I demonstrate using the find command in Linux and, through the use of some practical examples, I aim to help the reader become efficient when working with the Linux file system as well provide building blocks for further experimentation.

Basic Syntax and Semantics of the find Command

The find command in Linux is an essential tool at the disposal of every Linux user which provides efficient searching capabilities within the file system. Peeking at the help for the find command shows a command structure as shown below.

$ find --help
Usage: find [-H] [-L] [-P] [-Olevel] [-D debugopts] [path...] [expression]

default path is the current directory; default expression is -print
expression may consist of: operators, options, tests, and actions:
operators (decreasing precedence; -and is implicit where no others are given):
      ( EXPR )   ! EXPR   -not EXPR   EXPR1 -a EXPR2   EXPR1 -and EXPR2
      EXPR1 -o EXPR2   EXPR1 -or EXPR2   EXPR1 , EXPR2
...

Hmm ... maybe not the most helpful right?

Well like most things in Linux, or perhaps technology in general, the best way to become familiar with something new is to find a few examples and begin experimenting. This is what I hope to facilitate.

So, let me preceed my first example by making a couple directories named demo and demo/innerdemo along with a couple of text files to work with like so.

$ mkdir -p demo/innerdemo && cd demo
$ touch findme.txt ignoreme.txt innerdemo/another.txt
$ ls -l
total 0
-rw-rw-r-- 1 tci tci 0 Apr 20 14:10 findme.txt
-rw-rw-r-- 1 tci tci 0 Apr 20 14:10 ignoreme.txt

I could now use the find command to locate the findme.txt file in the current directory with the following command.

$ find -name findme.txt
./findme.txt

When find is used solely with the -name argument and a file name pattern then the command defaults to implicitly searching the current directory. You can also explicitly search the current directly by following the find command with a . to indicate the current directory should be searched like so.

$ find . -name findme.txt
./findme.txt

It may be clear from the last example but, I will still say it anyway, you can include a first argument to the find command which represents the starting directory you want to search from. For example, if I move back up one directly and I can explicitly say I want to start my search in the demo directory as shown below.

$ cd ..
$ find demo/ -name findme.txt
demo/findme.txt

Another thing worth mentioning is that the find command will recursively traverse the inner directories to find matching files burried within the directory it starts in. So, if I were to tell find to start in the demo directory but look for the another.txt file I created at the begining it actually will find it in the subdirectory named innerdemo.

$ find demo/ -name another.txt
demo/innerdemo/another.txt

Case Insensitive File Finding

The find command (and really most commands in Linux) performs it's search for the given pattern in an exact case matching manner. For example, if I move back into the demo directory and search for FINDME.TXT the find command will yield no results.

$ cd demo/
$ find -name FINDME.TXT
$ 

However, in the event you need to be able to loosen searches to include matches irrespective of case there is the -iname argument that can be used in place of -name.

$ find -iname FINDME.TXT
./findme.txt

Exclusionary File Finding

Sometimes it is useful to try to find all files except a specific one so, basically you are asking the find command to list all files that are different from a given file name pattern. This can be accomplished by including the -not argument.

For example, if I wanted to find all files except the ignoreme.txt file I would do that like so.

$ find -not -name ignoreme.txt
.
./innerdemo
./innerdemo/another.txt
./findme.txt

Narrowing the Search by File Type

One of the first things to understand about the Linux operating systems is that essentially everything in the OS is represented by a file of varying file types. Therefor, it is beneficial to be able to search for specific file types such as directories or character files and that is accompished by using the -type argument.

For example, if I want to find all directories within my demo directory I can do so by issuing -type argument followed by d for directory yeilding the innerdemo directory.

$ find -type d
.
./innerdemo

The man page for the find command gives the following different possible file types to filter on.

-type c
      File is of type c:

      b      block (buffered) special
      c      character (unbuffered) special
      d      directory
      p      named pipe (FIFO)
      f      regular file
      l      symbolic link; this is never true if the -L option or the -follow option is in effect, unless the symbolic link is broken.  If you want to search for symbolic links when -L is in effect, use -xtype.
      s      socket
      D      door (Solaris)

Searching for Files using Regular Expression Matching

An incredibly powerful feature of the find command is the ability to combine regular expression matching within the file pattern you are searching against. For example, if I wanted to find all files under the demo directory which end with the file extension .txt I could use the wild card regex matcher * like so.

$ find -name "*.txt"
./innerdemo/another.txt
./ignoreme.txt
./findme.txt

Size Based Searching

Something that has come up as a useful feature of the find command a few times when trouble shooting systems is the ability to look for files that exceed a particular size. This can be accomplished using the -size argument followed by a + or - sign to signify greater or lesser and then a number representing the size. So if I wanted to find all files in my /etc directory that are greater than 128 bytes I could do so using the following command.

$ sudo find /etc -size +128
/etc/ssh/moduli
/etc/vmware-tools/vgauth/schemas/XMLSchema.xsd
/etc/ssl/certs/ca-certificates.crt
/etc/lvm/lvm.conf
/etc/apparmor.d/cache/usr.lib.snapd.snap-confine.real
/etc/apparmor.d/cache/sbin.dhclient
/etc/apparmor.d/cache/lxc-containers

By default the size is interpretted in bytes but, you can specify a suffix to the value of the size argument using one of the options listed in the man page and reproduced below.

-size n[cwbkMG]
      File uses n units of space, rounding up.  The following suffixes can be used:

      `b'    for 512-byte blocks (this is the default if no suffix is used)
      `c'    for bytes
      `w'    for two-byte words
      `k'    for Kibibytes (KiB, units of 1024 bytes)
      `M'    for Mebibytes (MiB, units of 1024 * 1024 = 1048576 bytes)
      `G'    for Gibibytes (GiB, units of 1024 * 1024 * 1024 = 1073741824 bytes)

For example, if instead I look for all files greater than a Megabyte in the /usr/bin directory this is what I come up with.

$ sudo find /usr/bin -size +1M
/usr/bin/git-shell
/usr/bin/lxc
/usr/bin/vim.tiny
/usr/bin/git
/usr/bin/python3.6m
/usr/bin/strace
/usr/bin/git-upload-pack
/usr/bin/python3.6
/usr/bin/snap
/usr/bin/python2.7
/usr/bin/vim.basic
/usr/bin/x86_64-linux-gnu-dwp
/usr/bin/systemd-analyze
/usr/bin/perl
/usr/bin/perl5.26.1
/usr/bin/x86_64-linux-gnu-ld.gold
/usr/bin/node
/usr/bin/x86_64-linux-gnu-ld.bfd

Finding Files with a Specific Permission

Another useful thing that I've found myself doing with the find command is searching for files with a given permission. This is accomplishable by using the -perm argument followed by the permission value to be matched on. For demo purposes I will set the permission of the ignoreme.txt file in my demo directory to be only readable and writable by my tci user.

$ chmod 600 ignoreme.txt 
$ ls -l
total 4
-rw-rw-r-- 1 tci tci    0 Apr 20 14:10 findme.txt
-rw------- 1 tci tci    0 Apr 20 14:10 ignoreme.txt
drwxrwxr-x 2 tci tci 4096 Apr 20 14:46 innerdemo

Now I can search for files that only match that permission like so.

$ find -perm 600
./ignoreme.txt

Executing Other Commands On Find Command's Results

The last use case I would like to cover regarding the find command is the ability to feed the result of the find command into another command using the -exec argument. To set up this example I will change the findme.txt file within the demo directory to also have the same read / write permissions limited to my tci linux user like so.

$ chmod 600 findme.txt 
$ ls -l
total 4
-rw------- 1 tci tci    0 Apr 20 14:10 findme.txt
-rw------- 1 tci tci    0 Apr 20 14:10 ignoreme.txt
drwxrwxr-x 2 tci tci 4096 Apr 20 14:46 innerdemo

Now I can issue the find command along with the -perm argument paired with 600 permission value then end it with the -exec argument paired with the command to execute "chmod 755" followed by "{} \;" indicating the placeholder for each returned file matching permission of 600 and fed into the chmod 755 command as seen below.

$ find -perm 600 -exec chmod 755 {} \;
$ ls -l
total 4
-rwxr-xr-x 1 tci tci    0 Apr 20 14:10 findme.txt
-rwxr-xr-x 1 tci tci    0 Apr 20 14:10 ignoreme.txt
drwxrwxr-x 2 tci tci 4096 Apr 20 14:46 innerdemo

And as you can see the files starting with permissions of 600 (findme.txt and ignoreme.txt) were updated to the permissions of 755.

Resources For Learning More

thecodinginterface.com earns commision from sales of linked products such as the books above. This enables providing continued free tutorials and content so, thank you for supporting the authors of these resources as well as thecodinginterface.com

Conclusion

In this How To article on the linux find command I have talked through a number of common usage patterns of the find command and provided numerous examples to facilitate the discussion. At this point I am confident readers should be comfortable using the find command for common everyday tasks as well as exploring more of its capabilities.

As always, I thank you for reading and please feel free to ask questions or critique in the comments section below.

Share with friends and colleagues

[[ likes ]] likes

Community favorites for Linux

theCodingInterface