Learning Find – Searching for files and dirs on Linux/Mac

Sometimes you have to find files and folders on a computer. When you are working on a terminal in a remote system then there is no Apple Spotlight to help you search through your servers. Fortunately both Linux and Mac come with a command-line tool called ‘find’ that helps us find files and directories. It can even operate on files and directories in bulk. Lets learn some ‘find’ today!

Example Directory

I have prepared an example directory try out some of the search features of find. Just clone the repo and start a terminal session in the directory.

Find

The find command searches a given directory (and its subdirectories) for files based on a variety of attributes. When we type man find we read the following:

NAME
     find -- walk a file hierarchy

SYNOPSIS
     find [-H | -L | -P] [-EXdsx] [-f path] path ... [expression]
     find [-H | -L | -P] [-EXdsx] -f path [path ...] [expression]

content
     The find utility recursively descends the directory tree for each path listed, evaluating an expression (composed of the ``primaries'' and ``operands'' listed below) in terms of each file in the tree.

Find all files an directories

To search for all files and directories type:

$ find .
.
./LICENSE
./bin
./bin/hello.sh
./bin/bye.sh
./web
...

Find files only

To search for files only type:

$ find . -type f
./LICENSE
./bin/hello.sh
./bin/bye.sh
./web/index.html
...

Find directories only

To search for directories only type:

$ find . -type d
.
./bin
./web
./web/img
./java
./test-dir
./.git
...

Find a file with a specific name

To search for a file with a name type:

$ find . -type f -name "test1.txt"
./test-dir/test1.txt

Use a wildcard * to widen the search:

$ find . -type f -name "test*.txt"
./test-dir/test7.txt
./test-dir/test6.txt
./test-dir/test4.txt
./test-dir/test5.txt
./test-dir/test1.txt
./test-dir/test2.txt
./test-dir/test3.txt
./test-dir/test10.txt
./test-dir/test8.txt
./test-dir/test9.txt

Find files case insensitive

To search for files case insensitive type:

$  find . -type f -iname "test*.txt"
./test-dir/test7.txt
./test-dir/test6.txt
./test-dir/test4.txt
./test-dir/test5.txt
./test-dir/test1.txt
./test-dir/test2.txt
./test-dir/test3.txt
./test-dir/TEST_8.txt
./test-dir/TEST_9.txt
./test-dir/TEST_10.txt
./test-dir/test10.txt
./test-dir/TEST_2.txt
./test-dir/TEST_3.txt
./test-dir/TEST_1.txt
./test-dir/TEST_4.txt
./test-dir/TEST_5.txt
...

To search for Python files type:

$ find . -type f -iname "*.py"
./test-dir/test.py

To search for all image files type:

$ find . -type f -iname "*.jpg"
./michael-sum-565770-unsplash.jpg
./jonas-vincent-2717-unsplash.jpg
./web/img/michael-sum-565770-unsplash.jpg
./web/img/jonas-vincent-2717-unsplash.jpg
./web/img/raul-varzar-750436-unsplash.jpg
./web/img/jari-hytonen-538885-unsplash.jpg
./web/img/karina-vorozheeva-666313-unsplash.jpg
./web/img/nathalie-jolie-681356-unsplash.jpg
./web/img/eric-han-455080-unsplash.jpg
./web/img/mikhail-vasilyev-253977-unsplash.jpg
./raul-varzar-750436-unsplash.jpg
./jari-hytonen-538885-unsplash.jpg
./karina-vorozheeva-666313-unsplash.jpg
./nathalie-jolie-681356-unsplash.jpg
./eric-han-455080-unsplash.jpg
./mikhail-vasilyev-253977-unsplash.jpg

Find files base on time

To search for files, we can use the mmin, amin, cmin, mtime, atime or ctime. The ‘cma’ means created, modified or accessed. The min means minutes and time means days. To search for files that are created less than 10 minutes ago, type:

$ find . -type f -ctime -10
./LICENSE
./bin/hello.sh
./bin/bye.sh
./web/index.html
./web/readme.md
...

To search for files that were modified more than 10 days ago, type:

$ find . -type f -mtime +10

Find files on file size

To search for files over 5 megabytes type:

$ find . -size +5M
./web/img/jari-hytonen-538885-unsplash.jpg
./.git/objects/f2/d996ce562ad4203c33331f52824fb0e54d050f

To search for files less than 1MB type:

find . -size -1MB
.
./LICENSE
./bin
./bin/hello.sh
./bin/bye.sh
...

To search for empty files type:

$ find . -type f -empty
./bin/hello.sh
./bin/bye.sh
./web/readme.md
./java/readme.md
./test-dir/test7.txt
./test-dir/test6.txt
...

Search for access permissions

To search for files based on access permissions type:

$ find . -perm 777
./web/index.html
./web/readme.md
./web/img
./web/img/michael-sum-565770-unsplash.jpg
./web/img/jonas-vincent-2717-unsplash.jpg
./web/img/raul-varzar-750436-unsplash.jpg
./web/img/jari-hytonen-538885-unsplash.jpg
./web/img/karina-vorozheeva-666313-unsplash.jpg
./web/img/nathalie-jolie-681356-unsplash.jpg
./web/img/eric-han-455080-unsplash.jpg
./web/img/mikhail-vasilyev-253977-unsplash.jpg

Executing commands on result

we can execute a command in batch on the search result. Note the {} + part. We have to type that.

find . -size +5M -exec ls -alh {} +
-r--r--r--  1 dennis  staff   8.8M Nov 19 04:41 ./.git/objects/f2/d996ce562ad4203c33331f52824fb0e54d050f
-rwxrwxrwx@ 1 dennis  staff   8.9M Nov 19 04:33 ./web/img/jari-hytonen-538885-unsplash.jpg

Lets do something about those files that have ‘777’ permissions. Lets change that to ‘664’:

$ find . -type f -perm 777 -exec chmod 664 {} +
$ find . -type f -perm 664
./web/index.html
./web/readme.md
./web/img/michael-sum-565770-unsplash.jpg
./web/img/jonas-vincent-2717-unsplash.jpg
./web/img/raul-varzar-750436-unsplash.jpg
./web/img/jari-hytonen-538885-unsplash.jpg
./web/img/karina-vorozheeva-666313-unsplash.jpg
./web/img/nathalie-jolie-681356-unsplash.jpg
./web/img/eric-han-455080-unsplash.jpg
./web/img/mikhail-vasilyev-253977-unsplash.jpg

Lets change the directory with ‘777’ permission to ‘775’:

$ find . -type d -perm 777
./web/img
$ find . -type d -perm 777 -exec chmod 775 {} +
$ find . -type d -perm 775
./web/img

To find for files only in the current directory use the ‘maxdepth’ option:

$ find . -type f -iname "*.jpg" -maxdepth 1
 ./michael-sum-565770-unsplash.jpg
./jonas-vincent-2717-unsplash.jpg
./raul-varzar-750436-unsplash.jpg
./jari-hytonen-538885-unsplash.jpg
./karina-vorozheeva-666313-unsplash.jpg
./nathalie-jolie-681356-unsplash.jpg
./eric-han-455080-unsplash.jpg
./mikhail-vasilyev-253977-unsplash.jpg

Lets remove those files:

$ find . -type f -iname "*.jpg" -maxdepth 1 -exec rm {} +
$ find . -type f -iname "*.jpg" -maxdepth 1
<empty>

Conclusion

Find is available on both Linux and Mac. My knowing a few options you can effectively search for directories and files. Find also allows to operate on the search result with the ‘exec’ option. When used effectively, find can save you a lot of time doing file operations.

Share this article: Tweet this post / Post on LinkedIn