mike
mike

Reputation: 219

brace expansion command not recognized

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

Answers (1)

Charles Duffy
Charles Duffy

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

Related Questions