The Linux find command is a very helpful and frequently used command. It is used to locate files and directories. It allows you to specify a host of options that can help you locate what file or directory you may be looking for. The output of find can be used as input for other commands or operations.
I use the find command extensively and I am always looking for examples of how to use the find command.
In this post, I am going to list Linux find examples that I often use or need to know. I will also list some examples where the output of the find command is used to do some other task.
find examples
find # search from present working directory
.
./masterfile
./Masterfile
./A
./A/B
./a
./a/128k-aaab
./a/b ./a/128k-aaad ./a/128k-aaaa ./a/128k-aaac
Just typing find without any options will search for file and directories from your present working directory.
You can also specify a starting point or multiple starting points as shown below
find /home/bitnami
find /var/cache /usr/local/bin
if you do not have permission to access a directory you will see a message in your output.
var/cache/apt/archives/partial
find: ‘/var/cache/apt/archives/partial’: Permission denied
/var/cache/apt/archives/lock
If you only wanted to search for files or directories you can use the option -type to refine your search.
find . -type f # files
./masterfile
./Masterfile
./A/128K-aaac
./A/128K-aaad
./A/128K-aaaa
./A/128K-aaab ./a/128k-aaab ./a/128k-aaad ./a/128k-aaaa ./a/128k-aaac
find . -type d # directories
. ./A ./A/B ./a ./a/b
find based on file or directory name
You can refine your search by specifying a name and if needed make it case insensitive. You can specify multiple names or use a wildcard.
find -name masterfile ./masterfile
find . \( -name masterfile -o -name Masterfile \)
./masterfile
./Masterfile
find -iname masterfile ./masterfile ./Masterfile
find . -type f -name "*a"
./A/128K-aaaa
./a/128k-aaaa
Adding the -ls option lists the output in ls -dils format on standard output.
find . -type d -ls
1024311 4 drwxr-xr-x 4 bitnami bitnami 4096 Aug 10 17:10 .
1031022 4 drwxrwx--- 3 bitnami bitnami 4096 Aug 10 17:08 ./A
1031025 4 drwxrwx--- 2 bitnami bitnami 4096 Aug 10 17:03 ./A/B
1024590 4 drwxr-xr-x 3 bitnami bitnami 4096 Aug 10 17:05 ./a
1031023 4 drwxr-xr-x 2 bitnami bitnami 4096 Aug 10 17:09 ./a/b
maxdepth
find is a recursive command, it will scan all directories from the search path. You can however limit how deep you want find to traverse the directory path.
find . -maxdepth 1 -type f # maxdepth 0 is the starting directory only
./masterfile
./sbali
./Masterfile
#compare
find . -maxdepth 2 -type f
./masterfile
./sbali
./Masterfile
./A/128K-aaac
./A/128K-aaad
./A/128K-aaaa
./A/128K-aaab
./a/128k-aaab
./a/128k-aaad
./a/128k-aaaa
./a/128k-aaac
Note: -maxdepth should be the first option listed in the find command i.e. maxdepth 1 should be before type or size or other option used.
find based on file or directory permissions
Add the -perm option to look for files or directories based on their permissions.
find . -type d -ls -perm 0770
1024311 4 drwxr-xr-x 4 bitnami bitnami 4096 Aug 10 17:10 .
1031022 4 drwxrwx--- 3 bitnami bitnami 4096 Aug 10 17:08 ./A
1031025 4 drwxrwx--- 2 bitnami bitnami 4096 Aug 10 17:03 ./A/B
1024590 4 drwxr-xr-x 3 bitnami bitnami 4096 Aug 10 17:05 ./a
1031023 4 drwxr-xr-x 2 bitnami bitnami 4096 Aug 10 17:09 ./a/b
find based on file or directory uid, gid, user or group
You can search by uid, gid, user or group or a combination of these.
find . -uid 0 -ls
1026174 400 -rw-r--r-- 1 root root 409600 Aug 10 17:07 ./masterfile
find . -gid 0 -ls
1026174 400 -rw-r--r-- 1 root root 409600 Aug 10 17:07 ./masterfile
find . -user root -ls
1026174 400 -rw-r--r-- 1 root root 409600 Aug 10 17:07 ./masterfile
find . -group root -ls
1026174 400 -rw-r--r-- 1 root root 409600 Aug 10 17:07 ./masterfile
find based on size
find allows you to search based on size. Here are some examples
find . -type f -size -32k -ls # Less than 32k
1031038 16 -rwxrwx--- 1 bitnami bitnami 16384 Aug 10 17:08 ./A/128K-aaad
1031032 16 -rw-r--r-- 1 bitnami bitnami 16384 Aug 10 17:05 ./a/128k-aaad
find . -type f -size +399 -ls # more than 399 512 byte blocks
1026174 400 -rw-r--r-- 1 root root 409600 Aug 10 17:07 ./masterfile
1028148 400 -rw-r--r-- 1 bitnami bitnami 409600 Aug 10 17:10 ./Masterfile
You can also search for 0 byte file. In this example, I created an empty file and then used the size command to locate it.
touch sbali && find . -type f -size 0 -ls
1024108 0 -rw-r--r-- 1 bitnami bitnami 0 Aug 10 17:39 ./sbali
Combine options to refine your output
find . -type f \( -size 0 -o -size +300k \) -ls
1026174 400 -rw-r--r-- 1 root root 409600 Aug 10 17:07 ./masterfile
1024108 0 -rw-r--r-- 1 bitnami bitnami 0 Aug 10 17:39 ./sbali
1028148 400 -rw-r--r-- 1 bitnami bitnami 409600 Aug 10 17:10 ./Masterfile
find . -type f -size +300k -name "[a-z]*"
./masterfile
find based on access, creation or modification time
You can search based on:
- -amin n # File was last access n minutes ago.
- -atime n # File was access n*24 hours ago. -atime +1, implies at least two days ago.
- -cmin n # File status was changed n minutes ago.
- -ctime n # File status was changed n*24 hours ago.
- -mmin n # File data was last modified n minutes ago.
- -mtime n # File data was last modified n*24 hours ago.
Note: Your file system should have “atime” enabled for access time
find . -type f -atime 0
./masterfile
./sbali
./Masterfile
./A/128K-aaac
./A/128K-aaad
./A/128K-aaaa
./A/128K-aaab
./a/128k-aaab
./a/128k-aaad
./a/128k-aaaa
./a/128k-aaac
Combining find and other commands
Count the number of files found
find . -type f | wc -l
11
Print filenames sorted by size from small to largest
find . -type f -ls | sort -k 7 -n | awk ' { print $NF } '
./sbali
./a/128k-aaad
./A/128K-aaad
./a/128k-aaaa
./a/128k-aaab
./a/128k-aaac
./A/128K-aaaa
./A/128K-aaab
./A/128K-aaac
./masterfile
./Masterfile
find and delete files
This command is destructive. If any files match the criteria, it will delete them. Do not run this command unless you know what you are doing or you have a backup.
find <some_path> -type f -size 0 | xargs /bin/rm -f
find <some_path> -type f -size 0 -exec /bin/rm -f {} \;
The difference between -exec and xargs is that if you had a large number of files the rm would run against all of them one by one. In the case of xargs the input is grouped and the rm runs against them.
If you had a 1000 files to delete, -exec would run rm 1000 times vs xargs which will be much less.
If the command you are going to run does not accept more than one argument, then -exec would be the way to go.
Conclusion
I have only covered a few examples here that I end up using most of the times. I will keep adding more variations. Let me know if you need help with a particular option that I have not covered here and I will try to do my best.