Linux Commands

The Find -Exec Command on Linux

Your Linux system consists of thousands of files. Searching for them manually is a hassle. In such cases, your Linux system offers two distinct commands to find a particular file: the locate command and the find command. The find command, in particular, is a great tool when you want to specify file attributes and fine-tune your search for a file. Using the find command, you can even act on the file that you find using the exec argument. In this tutorial, we will be discussing the find -exec command.

The Find Command

The find command is slower than the locate command, but it searches the entire filesystem live! Further, using the find command, you can fine-tune your search using a large number of attributes. What this means in English is that you can fine-tune your search using almost any parameter you want. For example, you can search for files using the name of the file, the size of the file, the permission of the file, the modification times of the file, etc. Basically, it’s a very useful command!

The basic format of the find command is as follows:

find [place to search] <options>

Ex:

find / -name secret.txt

Here, the / represents the place to search for the file we want, and we have asked it to search for a file by the name of secret.txt.

Find Exec

The best feature of the find command is its exec argument that allows the Linux user to carry out any command on the files that are found. In other words, actions can be performed on the files that are found.

The find -exec command will take the following format:

find [path] [arguments] -exec [command] [placeholder] [delimiter]

We have to learn about a few things before we can use the exec argument:

  1. {} is called a placeholder. This placeholder will hold the result found by find.

So, if let’s say we’re looking for a file called secret.txt, then we would write:

find / -name secret.txt

This will find a whole bunch of files on my system when I want to execute a command. Instead of writing out the name of the file found, we will replace it with it the placeholder {}.

For example,

find / -name ‘secret.txt’ 2> /dev/null -exec cat {} \;

Note: In this case, let me also point out what the 2> /dev/null does. The 2 stands for standard error, which we want to ignore. Thus we send it to /dev/null. In essence, we’re taking the errors and throwing them away.

For now, let’s ignore the \; part and concentrate on the placeholder. Why did we add the {} after the word “cat”? Well, it will find the file I’m looking for, and then when it has found it, it will pass the file to the exec argument like this:

-exec cat {} \;

or

-exec cat /home/kalyani/secret.txt \;

So, it’s a Placeholder for the results chucked out by the find command!

  1. \; is a delimiter.

\; is a delimiter. This particular delimiter is how the find argument can end. When it ends in this manner, an action is taken on each result it finds.

For example, I have created three secret.txt files: secret.txt, secret2.txt, and secret3.txt.

Now, I’m going to issue the following command:

find / -name ‘secret*.txt’ 2> /dev/null -exec cat {} \;

As you can see from the picture, it found the three files, and it catted out their contents one by one. So, what does the \; do? Well, it ensures that action is taken on each file. In this case, we have three files. The cat command is first applied to the first result: secret2.txt. Then, it is applied to the second result: secret3.txt.  Finally, it is applied to the third result: secret.txt.

Here, when you use -exec cat {} \; argument, it executes the following:

cat secret2.txt;

cat secret3.txt;

cat secret.txt;
  1. \+ is another delimiter.

This is another type of delimiter. If and when this is used, action is taken on the results found.

For example:

find / -name ‘secret*.txt’ 2> /dev/null -exec ls {} \+

The following image will show you the difference between the \; and the \+:


Here, when you use -exec ls {} \; argument, it executes the following:

ls secret2.txt;

ls secret3.txt;

ls secret.txt;

While -exec {} \+ argument executes the following:

ls secret2.txt secret3.txt secret.txt;

Multiple Execs

Now, multiple -exec arguments can also be passed to the command.

The general format will be as follows:

find [path] [arguments] -exec [command_1] [placeholder] [delimiter] -exec [command_2] [placeholder] [delimiter]…-exec [command_N] [placeholder] [delimiter]

For example:

find / -name ‘secret*.txt’ 2> /dev/null -exec ls {} \; -exec cat {} \;

Here, as you can see, it takes the first result and passes it through the first command. Then, it passes it through the second command, and then goes to the second result.

In essence, the results are passed as follows:

ls secret2.txt; cat secret2.txt;

ls secret3.txt; cat secret3.txt;

ls secret.txt; cat secret.txt;

Another example:

find / -name ‘secret*.txt’ 2> /dev/null -exec ls {} \+ -exec cat {} \+

In this case, the results are passed as follows:

ls secret2.txt secret3.txt secret.txt; cat secret2.txt secret3.txt secret.txt;

Conclusion

Linux is a wonderful system with a gazillion files. However, it comes with only two distinct commands to search through the haystack for our needle. The better one of these two commands is the find command. The find command searches throughout the entire filesystem so that it will take a while. Further, it can take actions on the results found. This means that you can apply various commands on the files that are found. If you want to move them, if you want to remove them, or even do crazy things to the results of the find command, you can; your knowledge is the limit. So, the next time to have to do something to a file, you can do it using the find -exec command! We hope you found this article helpful. Check the other Linux Hint articles for more tips and information.

About the author

Kalyani Rajalingham

I'm a linux and code lover.