Reputation: 5901
My question is very similar to How to copy multiple files from a different directory using cp?
I don't want to use an explicit loop. Here is what I do:
$ FILES_TOOLS="fastboot,fastboot-HW.sh"
$ cp $HOME/tools/{$FILES_TOOLS} $TOP_DIR/removeme
cp: cannot stat `/home/johndoe/tools/{fastboot,fastboot-HW.sh}': No such file or directory
The files are present and destination is valid, because:
$ cp $HOME/tools/{fastboot,fastboot-HW.sh} $TOP_DIR/removeme
$ echo $?
0
Upvotes: 5
Views: 3005
Reputation: 530950
As long as the contents of the braces are literals, you can use brace expansion to populate an array with the full path names of the files to copy, then expand the contents of the array in your cp
command.
$ FILES_TOOLS=( $HOME/tools/{fastboot,fastboot-HW.sh} )
$ cp "${FILES_TOOLS[@]}" $TOP_DIR/removeme
Update: I realized you might have a reason for having the base names alone in the variable. Here's another array-based solution that lets you prefix each element of the array with a path, again without an explicit loop:
$ FILES_TOOLS=( fastboot fastboot-HW.sh )
$ cp "${FILES_TOOLS[@]/#/$HOME/tools/}" $TOP_DIR/removeme
In this case, you use the pattern substitution operator to replace the empty string at the beginning of each array element with the directory name.
Upvotes: 1
Reputation: 4038
This answer is limited to the bash.
Prepend an echo
to see what your cp
command turns into:
echo cp $HOME/tools/{$FILES_TOOLS} $TOP_DIR/removeme
You have to insert an eval
inside a sub-shell to make it work:
cp $( eval echo $HOME/tools/{$FILES_TOOLS} ) $TOP_DIR/removeme
Upvotes: 3
Reputation: 123410
I guess this is a problem of when the shell expansion actually occurs.
Yes. Different shells have different rules about brace expansion in relation to variable expansion. Your way works in ksh, but not in zsh or bash. {1..$n}
works in ksh and zsh but not in bash. In bash, variable expansion always happens after brace expansion.
The closest you'll get to this in bash is with eval
.
Upvotes: 1