Reputation: 893
I did a little experiment with the bash and even after reading the relevant parts of the advanced bash scripting guide I can't explain what I'm observing.
Test situation: A directory named "test" with a subdirectory "target" and two files: "a b" and "c d" (the names contain blanks). I want to move the files into the target directory and I'm making it way more complicated then necessary:
cp $(echo "'a b' 'c d'") target
This gives me the following result:
cp: Aufruf von stat für „'a“ nicht möglich: Datei oder Verzeichnis nicht gefunden
cp: Aufruf von stat für „b'“ nicht möglich: Datei oder Verzeichnis nicht gefunden
cp: Aufruf von stat für „'c“ nicht möglich: Datei oder Verzeichnis nicht gefunden
cp: Aufruf von stat für „d'“ nicht möglich: Datei oder Verzeichnis nicht gefunden
It is as if something is removing the single quotation marks from the output of the inner echo command. But if I do a:
echo $(echo "'a b' 'c d'")
the result is:
'a b' 'c d'
Can some bash guru point me to the documentation that makes me understand that? This would make my friday complete!
Edit: I realized too late, that the 's are not removed but ignored. This is even more confusing to me and needs to be explained as well.
Upvotes: 1
Views: 631
Reputation: 74595
The reason your approach isn't working:
cp $(echo "'a b' 'c d'") target
The command substitution (the bit between $(
and )
) is subject to word splitting. Your use of double quotes mean that echo
sees only one argument. However, the parent shell splits the output of echo
on white space into 'a b'
, 'c
and d'
, i.e. four separate words.
As always, using set -x
helps to visualise these things:
$ cp $(echo "'a b' 'c d'") target
++ echo ''\''a b'\'' '\''c d'\''' # the subshell
+ cp ''\''a' 'b'\''' ''\''c' 'd'\''' target # the parent shell
The single quotes show the boundaries of each word (although admittedly in this case, things are a little confused as you have your own single quotes in there too...).
If you were to put double quotes around the command substitution:
cp "$(echo "'a b' 'c d'")" target
then word splitting would not occur, meaning that the result of the command substitution would be a single word, although this would lead to a new problem:
$ cp "$(echo "'a b' 'c d'")" target
++ echo ''\''a b'\'' '\''c d'\'''
+ cp ''\''a b'\'' '\''c d'\''' target
Now cp
is expecting to find a file named 'a b' 'c d'
, which you don't have either.
For the sake of completeness, the best way to copy these files is:
cp 'a b' 'c d' target
Upvotes: 6
Reputation: 5305
You need to do eval cp $(echo "'a b' 'c d'") target
instead of cp $(echo "'a b' 'c d'") target
Upvotes: 1