There’s a powerful Linux command that can save you lots of headaches when used in the right places. It’s called find
. It walks through the file tree, starting from the provided path. Next, it prints each directory and file, including its path relative to the current working directory. Let’s explore the find command in Linux together!
Table of Contents
The basics
Just try it, enter the following and see what output you get:
$ find .
For me, the output looks like this:
. ./images ./images/cover.jpg ./scripts ./scripts/loop.sh ./scripts/arguments.sh ./scripts/words.txt
The first dot is simply the current directory. Find
will both output directories and files. If you only want to list files, use:
$ find . -type f
If you only want to list directories, use:
find . -type d
Expressions
So far for the basics. The find command in Linux also takes expressions, which further narrows down what files it should return. A useful expression that I use often is -mtime
. The following command returns all files that were modified more than 5 minutes ago:
$ find . -type f -mtime +5m
The m is a modifier, all available modifiers are listed in the following table:
Modifier | Meaning |
---|---|
s | second |
m | minute (60 seconds) |
h | hour (60 minutes) |
d | day (24 hours) |
w | week (7 days) |
The plus sign is important as well:
- a preceding plus sign means “more than n”
- a preceding minus sign means “less than n”
- neither means “exactly n”
Another useful expression is -name
, which will filter the results based on the file name. For the name, you can use a shell pattern. So the command find . -name "*.txt"
will only return files with the .txt
-extension.
Actions: using the results
With our new ninja scripting powers, we can now use the Linux find
command to return a bunch of files, feed them to a for loop in a Bash script, and do some awesome stuff with them, right?
True, but since it’s pretty obvious you want to perform some actions on the returned files, find has us covered already. No scripting is necessary.
Say you want to delete the files that match your criteria, you can simply add -delete
to your find
-command. This is obviously a bit dangerous, so before using this flag, always check the output of the find
-command without it first.
What gives us much more flexibility, is the -exec
flag. It allows us to execute any command. An example that you may have seen before is this one:
$ find /path/to/files* -mtime +5m -exec rm {} +
Let’s break it down:
- find all files in the given path that are modified more than 5 minutes ago
- execute the
rm
command (which deletes the files) {} +
is replaced with as many pathnames as possible for each invocation of the given utility (in our casels
)
This is actually a very efficient way of removing lots of files, like thousands or even millions.
A slight alternative to this command is:
$ find /path/to/files* -mtime +5m -exec rm {} \;
The difference is that rm
is now executed for every single file, instead of as many files per batch as your system allows. Which version you use depends on the command you’re executing on the results. If you can use the one with the plus sign, it’s a lot faster! That’s because the command is executed on many files at once, saving your OS lots of CPU cycles that are needed to open, start, run, and exit a program. However, some commands take just one file at a time and for those, the second version comes to the rescue.
And again: if you enter man find
(or visit the online man page), you’ll get the full documentation. But I’ll admit; I tend to google this stuff too because you generally get useful examples instead of needing to plow through the raw documentation. However, always try to understand exactly what it is you’re pasting into your terminal before hitting enter!