Question

I am trying to untar several files at once (I know I can do it differently but I want to make this work because it should work). So I do:

ls -1 *.gz | xargs tar xf

This produces one command from xargs with all files, and fails. -1 is optional - fails the same way without it.

In fact,

ls -1 *.gz | xargs -t echo
echo host1_logs.tar.gz host2_logs.tar.gz host3_logs.tar.gz host5_logs.tar.gz
host1_logs.tar.gz host2_logs.tar.gz host3_logs.tar.gz host5_logs.tar.gz

I tried unsetting IFS, setting it to newline. How do I make xargs on Mac OS X actually work?

Bonus question, in light of linebreak/loop problems I had with other commands before I wonder if Mac terminal is just broken and I should replace all utilities with GNU.

Was it helpful?

Solution

Use the -n argument to force xargs to run the given command with only a single argument:

ls -1 *.gz | xargs -n 1 echo

Otherwise, it tries to use each line from the input as a separate argument to the same invocation of the command.

Note that this will fail if any of the matched file names contain newlines, since ls has no way of producing output that distinguishes such names from a sequence of newline-free file names. (That is, there is no option to ls similar to the -print0 argument to find, which is commonly used in pipelines like find ... -print0 | xargs -0 to guard against such file names.)


Your question implies that you realize that you could do something like:

for f in *.gz; do
    tar xf "$f"
done

which is unlikely to be noticeably slower than any attempt at using xargs. In each case the process of spawning multiple tar processes is likely to outweigh any differences in looping in bash vs the internal loop in xargs.

OTHER TIPS

Basically you are passing all filenames to tar at once, which is not what you want as you have noticed. The above xargs -n 1 answer is neater, but you could also use the -I flag to run the tar command for each of the arguments (also useful for multi-parameter commands like mvor cp):

ls *.gz | xargs -I {} tar xzvf {}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top