m-ric
m-ric

Reputation: 5901

How to copy multiple files from a different directory using cp, variable and brackets?

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

Answers (3)

chepner
chepner

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

Perleone
Perleone

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

that other guy
that other guy

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

Related Questions