What does "{} \;" mean in the find command?
Solution 1:
If you run find
with exec
, {}
expands to the filename of each file or directory found with find
(so that ls
in your example gets every found filename as an argument - note that it calls ls
or whatever other command you specify once for each file found).
Semicolon ;
ends the command executed by exec
. It needs to be escaped with \
so that the shell you run find
inside does not treat it as its own special character, but rather passes it to find
.
See this article for some more details.
Also, find
provides some optimization with exec cmd {} +
- when run like that, find
appends found files to the end of the command rather than invoking it once per file (so that the command is run only once, if possible).
The difference in behavior (if not in efficiency) is easily noticeable if run with ls
, e.g.
find ~ -iname '*.jpg' -exec ls {} \;
# vs
find ~ -iname '*.jpg' -exec ls {} +
Assuming you have some jpg
files (with short enough paths), the result is one line per file in first case and standard ls
behavior of displaying files in columns for the latter.
Solution 2:
From the manpage for the find
command :
-exec command ;
Execute command; true if 0 status is returned. All following arguments to find are taken to be arguments to
the command until an argument consisting of `;' is encountered. The string `{}' is replaced by the current
file name being processed everywhere it occurs in the arguments to the command, not just in arguments where it
is alone, as in some versions of find. Both of these constructions might need to be escaped (with a `\') or
quoted to protect them from expansion by the shell.
So here's the explanation:
{}
means "the output of find
". As in, "whatever find
found". find
returns the path of the file you're looking for, right? So {}
replaces it; it's a placeholder for each file that the find
command locates (taken from here).
The \;
part is basically telling find
"okay, I'm done with the command I wanted to execute".
Example:
Let's say I'm in a directory full of .txt
files. I then run:
find . -name '*.txt' -exec cat {} \;
The first part, find . -name *.txt
, returns a list of the .txt
files. The second part, -exec cat {} \;
will execute the cat
command for every file found by find
, so cat file1.txt
, cat file2.txt
, and so on.