I am trying to pipe file to rm via xargs. I understand that what I am tryng to do could be done by git clean but I am practicing the cli.
I tried this:

for files in $(git status --porcelain| sed 's/^??//g'); do echo $files; done | xargs rm -rf

but it did not work. I figured it was because when running this:

for files in $(git status --porcelain| sed 's/^??//g'); do echo $files; done | xargs

The files seem to be in 1 string separated by a space.
But when I run for files in $(git status --porcelain| sed 's/^??//g'); do echo -n $files; done the files are displayed in the console in a separate line.

So (if I am right on this) what is the difference between:
for files in $(git status --porcelain| sed 's/^??//g'); do echo -n $files; done | xargs

for files in $(git status --porcelain| sed 's/^??//g'); do echo -n $files; done

and the files in the second case are displayed each in each own line and in the first case it is one string? And how would I fix this so that it works with rm -rf?

  • The files are indeed on separate lines. It's just that you're collecting them back onto a single line by piping them into xargs. Try xargs -n1 which will force it to only process a single argument at a time to prove this to yourself.
    – Celada
    Feb 27, 2015 at 21:54
  • @Celada:Now I get the files with no space as 1 string
    – Jim
    Feb 27, 2015 at 21:57
  • 3
    You have not use xargs at all: just to replace echo by rm
    – Costas
    Feb 27, 2015 at 21:57
  • @Celada:Hm. I was using echo -n when trying to figure this out. You are right when I do the same command with -n1 I get the files at a separate line, but rm does not do anything
    – Jim
    Feb 27, 2015 at 22:00
  • As said above, you are not using xargs correctly. This should do what you are trying to do if the rest of your syntax is right. git status --porcelain | sed 's/^??//g' | xargs rm -rf Feb 28, 2015 at 1:16

1 Answer 1


You are making your life more complicated than necessary ;-)

If the subshell command (the expression inside your $()) already provides a list of filenames, and the "target command" (rm -rf in your case) already accepts a list of filenames, why not just use

git status --porcelain| sed 's/^??//g' | xargs rm -rf

Or, if you wish to practice a "for loop" in bash, you don't need xargs:

for f in $(git status --porcelain| sed 's/^??//g') ; do
    rm -rf $f

BTW... doubly check your 'rm -rf' commands (adding an 'echo' before 'rm -rf') before executing them, silly errors happen and you'll regret it!!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.