Finding files in linux

Table of contents

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, eg 644) or symbolic form (%M, eg -rw-r--r--; same as ls -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

More articles

Write modern javascript for older browsers with babel and browserify

Write modern frontend code even for outdated target browsers

5 neat javascript tricks to make your life easier

Making your code more elegant with lesser-known language features

Embracing python context managers

Simplifying your code by automating resource handling

The downsides of source-available software licenses

And how it differs from real open-source licenses

Configure linux debian to boot into a fullscreen application

Running kiosk-mode applications with confidence

How to use ansible with vagrant environments

Painlessly connect vagrant infrastructure and ansible playbooks