Reputation: 219
How can I repeat a shell command using brace expansion (or another simple method), adjusting certain parameters for each iteration of the command? Here's a simple example of what I'd like to do (but with more lengthy commands): cp a b; cp a c;
Obviously, that works if I type that into a terminal. But I'd like to be able to generate that in a more compact way. I tried to use bash brace expansion but it gives me a command not found error:
~/test $ ls
a
~/test $ cp\ a\ {b,c}\;
cp a b;: command not found
~/test $
Using backticks also doesn't work.
~/test $ `cp\ a\ {b,c}\;`
cp a b;: command not found
Upvotes: 1
Views: 546
Reputation: 295403
Doing this in a correct and safe manner is not as terse as you'd like:
for arg in b c; do cp a "$arg"; done
The quotes are important -- otherwise, a file named filename with a space
will be converted into four separate arguments, filename
, with
, a
and space
. (If you're literally only processing b
and c
, that's not an issue, but establishing habits that would get you in hot water later isn't good practice).
Your question and comments posit use of eval
to process the result of a brace expansion, but that's somewhat evil:
eval "cp a "{b,c}";"
The problem with this is that while it works well with very simple parameters, it will behave in surprising and unexpected ways with arguments that aren't so simple (filenames that contain shell syntax, in particular). As such, it's extremely poor practice.
With respect to backticks --
`cp a b c`
is exactly the same as
cp a b c
...except that it also reads from cp
's stdout, substitutes the output of cp into the resulting command, and then runs that command as well.
So,
echo `cp a b c`
first runs cp a b c
, reads the output -- which is empty, since even if there's an error, it's written to stderr, not stdout, and then runs
echo
...with no arguments. If cp did emit something to its stdout, then that string would be parsed into arguments and those arguments would be passed to echo
.
Upvotes: 1