The find command is installed by default on most linux distributions and, as the name implies, helps us find files or directories. But once you dive deeper into the capabilities of this tool, you see how much more than simple finding it can do for you.
Finding executables
In case you are looking for executables or information related to them, there are better commands than find
:
which python
Will print the path of the command python
, or nothing if no command could be found in any directories from $PATH
.
If you need more information, use whereis
instead:
whereis python
This will print out all matching executables found in $PATH
, as well as their documentation files if present.
There is a key difference between which
and whereis
: If you have multiple commands with the same name in different directories, which will only print the first one it finds (in order specified in $PATH
) and exit, while whereis
will list them all. This can help you find name collision issues, for example when a custom command in /usr/local/bin
gets overriden by an executable in /bin
with the same name.
Basic find
usage
At it's core, the find command's syntax is really simple, you just give it a path and some conditions to filter files by:
find /path conditions...
If you for example wanted to find a file named "cat.jpg", you could filter by name:
find . -type f -name "cat.jpg"
Here we used -type f
to limit our search to files only and -name "cat.jpg"
to only return results matching this exact file name. Note the quotes around the filename, this is important to prevent shells like bash from interpreting it before handing it to the find
command.
If you only know part of the filename you are looking for, you can use pattern matching as well:
find . -type f -name "*.jpg"
Searching will, by default, include all subdirectories of the target directory given to it. This can be limited with the -maxdepth
parameter.
find . -type f -maxdepth 0 -name "*.jpg"
The -maxdepth
parameter defines how many directory levels may be traversed down while searching, so 0 makes it ignore subdirectories entirely.
Controlling output with printf
The default behaviour is to simply print the path of found files, but this may not always be the information you need. For this reason, you can specify your own output format using the -printf
argument:
find /etc -type f -name "*.conf" -printf "%u\t%p\n"
For each file ending in .conf in the /etc directory, this will print first the user owning that file (%u), then a tab (\t) and finally the the path of the file (%p). The formatting used for this formatting is not the same as used in printf or similarly-named functions you may know from programming languages. The directive %s would usually be interpreted as a string, but for find it will return the size of the file instead.
Here is a list of find's most common formatting directives:
%p
: The path to the file%f
: The base name of the file (without directories)%s
: The size of the file in bytes%u
and%g
: The user / group owning that file%U
and%G
: The id of the user / group owning the file%a
and%t
: The last time the file was accessed (%a
) or modified (%t
)%m and %M
: The permissions set for the file, in octal (%m
, eg644
) or symbolic form (%M
, eg-rw-r--r--
; same asls -l
)
Combining with other commands
While find alone can already do a lot of things, it's full potential is only reached when combined with other tools, like sort
to order output and head
, tail
or wc
to limit or count results.
A real-world application of this is to find the 10 largest log files in /var/log, sorted by size:
find /var/log -type f -name "*.log" -printf "%s\t%p\n" | sort -nr | head -n 10
This will only consider files ending in .log
, to exclude rotated and compressed archives like .gz
.
Alternatively, you could count the number of log files exceeding 100kb:
find /var/log -type f -name "*.log" -size +100k | wc -l
Some examples
These examples should give you an idea of how flexibly you can use the find
command:
Find config files that were modified in the last 10 minutes:
find /etc -type f -name "*.conf" -mmin -10 -printf "%t\t%p\n"
Change all files with 777
permissions to 644
:
find . -type f -perm 0777 -print -exec chmod 644 {} \;
Remove empty directories:
find . -type d -empty -print -delete
Find duplicates of source_file.txt
:
find . -samefile source_file.txt
Delete temporary files older than a day:
find /tmp -type f -mmin +24 -print -delete
More information
There are way too many options for the find command to list them all in a single post. Fortunately, it comes with an excellent man page listing each and every one of them. Check it out yourself!
man find