6

I'm having some trouble with this command under bash in Ubuntu:

rm $(find . -name "*.exe")

My aim is to remove, recursively, all files ending in .exe. But some files have white spaces and this breaks the command.

Any suggestions on how to approach this problem?

Jens Erat
  • 17,507
  • 14
  • 61
  • 74
DrBeco
  • 1,915
  • 2
  • 17
  • 16

4 Answers4

17
find . -name "*.exe" -exec rm -f '{}' +

This has find format the command and arguments, and it carefully avoids mangling the names (by passing each one as a separate argument to rm). The '+' means "do as many as you can reasonably in one execution of rm".

Jonathan Leffler
  • 5,003
  • 1
  • 30
  • 37
  • 3
    `find(1)` has the `-delete` action (maybe just GNU find only) which will save all the subprocesses and cumbersome command line options. `find . -name '*.exe' -delete` – camh Jul 12 '11 at 04:35
  • @camh: follow the link to the POSIX documentation; `-delete` is not included. It is in GNU `find`; the question is for Linux; so it is possible to use `-delete`. However, all the world is not Linux, and a portable answer maybe of use. – Jonathan Leffler Jul 12 '11 at 04:44
3

You can pipe the output from find into xargs, specifying that only newlines should be considered as delimiters between filenames:

find -name '*.exe' | xargs -d \\n rm

The more portable way to do this is to use the null character as the delimiter:

find -name '*.exe' -print0 | xargs -0 /bin/rm

See find's manpage for an example that does this.

Another option is to use the command you used, but to set bash's internal argument delimiter to newlines-only:

IFS=$'\n'; rm $(find . -name "*.exe");

Here the $'...' quoting construct is used to create a newline character. This approach will be less resilient in the case of a long list of filenames than will using xargs.

intuited
  • 3,291
  • 7
  • 30
  • 40
  • 1
    There's no real point in using anything other than the `-print0` and `-0` options; the other doesn't work correctly if the names contain newlines (and that is a valid character in a Unix file name). Similarly with the IFS hack. Note that these are GNU-specific (though eminently sensible) extensions to the standard. – Jonathan Leffler Jul 12 '11 at 04:47
  • @Jonathan: I usually use `-d` myself just because it's less typing, and in practice filenames (at least for me) never contain newlines. There's also the advantage that you can filter the output of `find` through other programs (grep, tail, etc) before sending it to `xargs`. – intuited Jul 12 '11 at 10:50
1

Simply pass the -delete option to find:

find . -name "*.exe" -delete

This saves you from quoting and any other filename hassles and is presumably faster than -exec because no new processes need to be spawned.

mainzelM
  • 154
  • 3
0

Manually escaping the characters may help you.

find . -name "*.exe" | sed -s 's/\ /\\ /' | xargs rm -f
  • Not a reliable technique; all else apart, `xargs` splits names at blanks. You might use `find . -name "*.exe" -print0 | xargs -0 rm -f`, where the `-print0` ends file names with ASCII NUL and the `-0` means that `xargs` reads names ending with ASCII NUL. Note that these are GNU-specific (though eminently sensible) extensions to the standard. – Jonathan Leffler Jul 12 '11 at 04:46
  • @Jonathan True.. Your answer is definitely better. –  Jul 12 '11 at 05:51