This question already has an answer here:
Say I have a variable $ARGS
which contains the following:
file1.txt "second file.txt" file3.txt
How can I pass the contents of $ARGS
as arguments to a command (say cat $ARGS
, for example), treating "second file.txt"
as one argument and not splitting it into "second
and file.txt"
?
Ideally, I'd like to be able to pass arguments to any command exactly as they are stored in a variable (read from a text file, but I don't think that's pertinent).
Thanks!
It's possible to do this without either bash arrays or
eval
: This is one of the few places where the behavior ofxargs
without either-0
or-d
extensions (a behavior which mostly creates bugs) is actually useful....or...
...or, letting
xargs
itself do the invocation:As mentioned by Jonathan Leffler you can do this with an array.
An array's index starts at 0. So if you wanted to
cat
the first file in your array you would use the index number 0."${my_array[0]}"
. If you wanted to run your command on all elements, replace the index number with@
or*
. For instance instead of"${my_arryay[0]}"
you would use"${my_array[@]}"
Make sure you quote the array or it will treat any filename with spaces as separate files.Alternatively if for some reason quoting the array is a problem, you can set IFS (which stands for Internal Field Separator) to equal a newline. If you do this, it's a good idea to save the default IFS to a variable before changing it so you can set it back to the way it was once the script completes. For instance:
It's probably better to not mess around with IFS unless you have to. If you can quote the array to make your script work then you should do that.
For a much more in depth look into using arrays see:
Without
bash
isms, plain shell code might need aneval
:Output:
Note that
eval
is powerful, and if not used responsibly can lead to mischief...