How to Use the find Command With exec
Find works on searching files based on a number of criteria. The exec command gives you the ability to work on those results. Here are some examples of find exec command combination.
The find command in Linux is an excellent tool to find files and directories based on given criteria.
You can take your findings to the next level by actually doing specific operations on the found files.
For example, you found all the files with .jpeg extension. How about renaming them with .jpg extension?
You cannot just pipe redirect the find command output to another command. It won't work that simply.
You have two ways to execute other commands on the result of the find command:
- use xargs
- use exec
There is already a detailed article on xargs command. This tutorial will focus on combining find and exec commands.
Using exec command with the output of find command
The basic syntax to execute find with exec is as follows:
find [path] [arguments] -exec [command] {} \;
Here's a quick explanation:
- [command] is what you want to execute over results given by the find command.
- {} is a placeholder that is used to hold results given by the find command.
- \; says that for each found result, the [command] is executed. You need to escape the ; here and hence \;.
There is another syntax that is slightly different from the above and is as follows:
find [path] [arguments] -exec [command] {} +
Here, + says for every result of the find command, the [command] is executed only once. All the results are passed to the [command] as arguments together. +
does not need to be escaped with \+
.
Still confused about the use of {} \;
and {} +
?
{} \;
is like this (executing the commands for each found result):
ls file1.txt
ls file2.txt
ls file3.txt
{} +
is like this (executing the command once with all results argument):
ls file1.txt file2.txt file3.txt
While it may seem like using {} +
is the better option here, it's the opposite. If the find commands throw 50 results, you cannot pass them all as arguments together because there are restrictions on maximum command line length.
This is why you are better with {} \;
unless you know exactly what you need.
Practical examples of combining find and exec commands
Let me share some common examples of find exec commands so that you can understand them better.
1. Find and display file attributes
In the first simple example of find exec command, I am going to display all the lock files that are under the /tmp directory and display their properties.
sudo find /tmp/ -type f -name *lock -exec ls -l {} \;
Here's the result:
sagar@LHB:~$ sudo find /tmp/ -type f -name *lock -exec ls -l {} \;
-r--r--r-- 1 gdm gdm 11 Jul 17 08:01 /tmp/.X1024-lock
-r--r--r-- 1 gdm gdm 11 Jul 17 08:01 /tmp/.X1025-lock
2. Find and rename files
Yes, using find with exec you can rename files easily. The mv command is used for renaming the files. I'll be doing the same.
sudo find /home/sagar/Downloads/ -type f -name 'ubuntu*' -exec mv {} {}_renamed \;
The above command finds the files that start with the name ubuntu and store them inside the placeholder. Once the process of storing results inside the placeholder, it will add "_renamed" at the end of each file stored inside the placeholder.
3. Collect and store file sizes
In this example, I will show you how you can collect the size of available files under a certain directory and create a file to save the given output.
I will collect each file's size under the /tmp directory and save the output under the /root directory with the filename of du_data.out
sudo find /tmp/ -type f -exec du -sh {} \; > /root/du_data.out
Now, let's have a look at what the recently created file under /root directory looks like.
4. Remove files with specific parameters
Please be extra careful while automatically removing files. It could be catastrophic if you don't pay attention. Either use the interactive delete with rm -i
or see the result of the find command first.
Another common example of the find exec command combination is to find files greater than a certain size and remove them. This works well if you are cleaning old logs.
I am removing files larger than 100 MB for demonstration under my Desktop directory.
find ~/Desktop -size +100M -exec rm {} \;
Similarly, you can also remove files based on how old they are. For example, let's remove files that are older than 10 days.
sudo find /tmp/ -type f -mtime +10 -exec rm {} \;
Here I used -mtime which identifies data modified in the last 24 hours and when paired +10 with it, it found and deleted files that are older than 10 days.
5. Execute specific tools
There are various cases where you may want to start certain tools or packages after finding the files.
For example, when I'm searching for any mp3 file, I want to run id3v2 which will bring details about found mp3 file.
find . -name "*.mp3" -exec id3v2 -l {} \;
id3v2 is the package that will show the details about the mp3 file and -l is used to show each mp3 tag associated with found mp3.
6. Change the ownership of files and directories
Changing the ownership of files and directories is another example of how powerful the combination of find and exec is.
Here, I am looking for the files owned by the user named sagar
and then change their ownership to milan
.
sudo find /home/sagar/disk/Downloads -user sagar -type f -exec chown milan {} \;
7. Changing the permission of files
So how about changing permissions of files using find and exec?
sudo find /home/sagar/disk/Downloads -type f -exec chmod 644 {} \;
In the above command, I used -type f so the command will only be applied to files under the given directory.
8. Collect md5sum for each file
In this example, I will demonstrate how you can collect md5sum for each available file under the /tmp directory.
sudo find /tmp/ -type f -exec md5sum {} \;
As you can see, the applied command collected md5sum for each available file with their names and md5sum.
But what if you want to save this output and to certain directly with a different name? you just have to follow the given command and change names directly accordingly:
sudo find /tmp/ -type f -exec md5sum {} \; > /Documents/checksumdata.out
9. Combine exec with grep Command
The find command works on the file names. The grep command works on the contents of the files.
Combine the find and grep together with exec and you got yourself a powerful search tool in the Linux command line.
For example, the command below searches for all the files that have .hbs
extension. With grep, it searches inside the content of those .hbs files for the string 'excerpt'.
find . -type f -name "*.hbs" -exec grep -iH excerpt {} \;
With the -H
option, grep command will show the file names for each match. Here's the output:
sagar@LHB:~/Downloads/casper-hyvor$ find . -type f -name "*.hbs" -exec grep -iH excerpt {} \;
./author.hbs: <div class="post-card-excerpt">{{bio}}</div>
./partials/post-card.hbs: {{#if excerpt}}
./partials/post-card.hbs: <div class="post-card-excerpt">{{excerpt}}</div>
./post.hbs: {{#if custom_excerpt}}
./post.hbs: <p class="article-excerpt">{{custom_excerpt}}</p>
./tag.hbs: <div class="post-card-excerpt">
Bonus tip: Find with multiple exec commands
Yes, you can chain multiple exec commands with single find command.
Let me take the same example that you saw in the previous section and use two exec commands.
find . -type f -name "*.hbs" -exec echo {} \; -exec grep excerpt {} \;
It'll search for the .hbs files first and then echo their name with first exec command. And then, those files will be searched for the "excerpt" string.
The output will be slightly different than the one in the previous command:
sagar@LHB:~/Downloads/casper-hyvor$ find . -type f -name "*.hbs" -exec echo {} \; -exec grep excerpt {} \;
./index.hbs
./page.hbs
./default.hbs
./author.hbs
<div class="post-card-excerpt">{{bio}}</div>
./error-404.hbs
./error.hbs
./partials/icons/twitter.hbs
./partials/icons/fire.hbs
./partials/icons/lock.hbs
./partials/icons/loader.hbs
./partials/icons/rss.hbs
./partials/icons/avatar.hbs
./partials/icons/facebook.hbs
./partials/post-card.hbs
{{#if excerpt}}
<div class="post-card-excerpt">{{excerpt}}</div>
./post.hbs
{{#if custom_excerpt}}
<p class="article-excerpt">{{custom_excerpt}}</p>
./tag.hbs
<div class="post-card-excerpt">
Conclusion
Find is an already powerful command for searching files based on a number of criteria. The exec command gives you the ability to work on the result of the find command.
The examples I shared here are just a glimpse. Together, the find-exec command combination gives you endless possibilities for doing things in the Linux command line.
A software engineer who loves to tinker with hardware till it gets crashed. While reviving my crashed system, you can find me reading literature, manga, or watering my plants.