Ubuntu – Difference between “xargs” and command substitution

bashxargs

In many cases I use command substitution instead of xargs. For example rm $(ls) is the same as ls | xargs rm

What really are the differences between them?

I think one of the differences is that command substitution runs in subshell while xargs runs in current shell but I am not sure.

Please list the differences.

Best Answer

One difference is that when using command substitution instead of a pipe, the size of the data passed is limited by the size of the command buffer, so it is truncated in some cases with no warning. This also means that that the whole command output must be produced, and stored in memory, before it is passed to the next command, so for large outputs you can use much more memory than necessary.

Another issue with the first method is that the output is split on whitespace, so you can't handle filenames with spaces in them. xargs also is affected by the whitespace problem, but it can be fixed by changing the delimiter used. To properly handle filenames by the way, you would need to use the null byte as a delimiter in the second example.

A third issue is that globs are expanded, so if a file has asterisks or question marks in its name, there will be unexpected results.

You can find a nice discussion on the issue here: http://mywiki.wooledge.org/ParsingLs

The correct syntax would be

echo rm *

or if you must use xargs,

find . -maxdepth 1 -print0 | xargs -0 echo rm

Remove echo when the output looks correct.