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
Depth of search
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.