Pipe the output of a command to rm command

Following command prints the path of the song being played.

mpc | head -n 1 
songs/oldSongs/Mukesh_D/041 KANHAIYA = YAAD AAYI ADHI RAAT KO.mp3

Can I delete this file by modifying the command I used to print it?

Asked By: Dilawar


You can do this with rm -i "/path/to/music/library/$(mpc -f %file% | head -n 1)". However, be warned that this will break if the filename contains a newline. As the output of mpc -f %file% is relative to your music library path, you need to prepend it to the output.

Answered By: Chris Down

Unless you are able to produce NULL-terminated filenames (as e.g. find -print0) you can try to quote the filenames by piping it through sed 's/^/"/;s/$/"/', which adds the quotes at the beginning and end of a line. Note however, that in this case you need to have:

  • one file per line
  • no double quotes in the filenames

The advantage is, that you can pretty much arbitrarily transform the output (e.g. when you decide not to rename rather than to delete or when you need to strip parts of the output).

Answered By: peterph

To answer your more general question, that’s the job of xargs to take a list of words on standard input and convert it to a list of arguments to a command.

However, xargs expects the list as a space, tab and newline (and possibly more blank characters depending on the locale and xargs implementation) separated list of words where single quotes, double quotes and backslash are used to escape those separators (with varying behaviors with regards to nesting of those by different implementations of xargs).

If the input is a newline-terminated list, the canonical way to convert it to the format expected by xargs is to escape every character (though only, backslash, single quote, double quote, underscore (potentially), space and tab (and possibly other blanks if not in the C locale) are necessary) but newline with a backslash character, which we can do with sed.

mpc | head -n 1 | sed 's/./\&/g' | xargs rm --

Note that some xargs implementations have a rather low limit on the maximum line length they expect on stdin, so you may want to only escape the necessary characters with those.

With GNU xargs at least, you don’t need to do that, you can do:

mpc | head -n 1 | xargs -rd 'n' rm --

(also using the GNU specific -r option to avoid running any command if the input is empty).

Answered By: Stéphane Chazelas

If it’s safe to assume you do not have files with double quotes or newlines you can do:

mpc | head -n 1 | sed  's/^/"/g ; s/$/"/g' | xargs rm --

The sed adds quotes around your file name, and xargs turns the input it gets to arguments for the command it is running (in this case, the rm command).

Answered By: Didi Kohen

Personally, while I think xargs is fun and all, I kind of prefer loops for this kind of thing. Why? Well, it gives you more flexibility… and also gives you a fairly easy way to handle spaces:

mpc | head -n 1 | while read filename
  ls -al "$filename"  # Look at the file you're deleting
  rm -i "$filename"   # Ask if you want it deleted (or not)

When you use a while loop like that, your data gets pumped into whatever variable name comes after “read”; in order to reference the variable, you then need the leading dollar sign. The quotes are there to gracefully handle spaces, so they don’t look like delimeters. Loops like this, while less elegant than a simple one-liner, offer you more flexibility and come in crazy handy in the long run.

Answered By: Ken
Categories: Answers Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.