Bash – What does {} means

bash

I want to delete files, which have size = 0. So I tried:

find ./ -size 0 | xargs rm

But it has a problem with files, which names begin with space.
I found this:

find ./ -size 0 -exec rm -i {} \;

It works. I think my way with xargs is too sophisticated for this.

What does {} \; means?

Could you explain me? My English is not very good, so please write simply.

Best Answer

{} has absolutely no meaning to bash, so is passed unmodified as an argument to the command executed, here find.

On the other hand, ; has a specific meaning to bash. It is normally used to separate sequential commands when they are on the same command line. Here the backslash in \; is precisely used to prevent the semicolon to be interpreted as a command separator by bash and then allow it to be passed as a parameter to the underlying command, find. Quoting the semicolon, i.e. ";" or ';', could have been an alternate way to have it stayed unprocessed.

The command:

find ./ -size 0 -exec rm -i {} \;

means: find in the current directory (note that the / is useless here, . cannot be but a directory anyway) anything that has a size of 0 and for each object found, run the command rm -i name, i.e. interactively prompt for each file if you want to remove it. {} is replaced by each file name found in the executed command. One nice feature is that this file name is strictly a single argument, whatever the file name (even containing embedded spaces, tabs, line feeds, and whatever characters). This wouldn't be the case with xargs, unless non portable hacks are used. The final ; is there to end the -exec clause. The reason why its end needs to be delimited is that other find options might follow the -exec one, although it is rarely done. e.g.:

find . -name "*.js" -exec ls -l {} \; -name "special*" -exec wc -l {} \;

One issue with this command is that it won't ignore non plain files, so might prompt the user to delete sockets, block and character devices, pipes, and directories. It will always fail with the latter even if you answer yes.

Another issue, although not really critical here, is that rm will be called for each file that has a zero size. If you substitute the -exec ending from /; to +, find will optimize the sub-process creation by only calling rm the minimal possible number of times, often just once.

Here is then how I would modify this command:

find . -type f -size 0 -exec rm -i {} +