Piping find -name to xargs results in filenames with spaces not being passed to the command

43,316

Solution 1

You can tell find and xargs to both use null terminators

find . -name "*.txt" -print0 | xargs -0 rm

or (simpler) use the built-in -delete action of find

find . -name "*.txt" -delete

or (thanks @kos)

find . -name "*.txt" -exec rm {} +

either of which should respect the system's ARG_MAX limit without the need for xargs.

Solution 2

The xargs command uses tabs, spaces, and new lines as delimiters by default. You can tell it to only use newline characters ('\n') with the -d option:

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

Source answer on SO.

Solution 3

Incidentally, if you used something other than find, you can use tr to replace the newlines with null bytes.

Eg. the following one liner deletes the 10 last modified files in a directory, even if they have spaces in their names.

ls -tp | grep -v / | head -n 10 | tr "\n" "\0" | xargs -0 rm

Share:
43,316

Related videos on Youtube

Ashley
Author by

Ashley

Updated on September 18, 2022

Comments

  • Ashley
    Ashley over 1 year

    Normally to remove files with spaces in their filename you would have to run:

    $ rm "file name"
    

    but if I want to remove multiple files, e.g.:

    $ find . -name "*.txt" | xargs rm
    

    This will not delete files with spaces in them.

  • kos
    kos over 8 years
    Can't upvote it twice tough :) since you mentioned ARG_MAX I'll also mention that find . -name "*.txt" -exec rm {} \; would be a "safe shot"
  • Joshua
    Joshua over 8 years
    Thus sayeth the master: always remember xargs -0.
  • Kev
    Kev over 5 years
    Super important point: -print0 must be the last option (or at least after -name "*.txt") otherwise this will hit files no longer limited to *.txt...