How do I copy multiple files by wildcard?

How about something like this in bash:

for file in ABC.*; do cp "$file" "${file/ABC/DEF}";done

you can test it by putting echo in front of the cp command:

for file in ABC.*; do echo cp "$file" "${file/ABC/DEF}";done

To do this efficiently with a large number of files, it is better to avoid a starting a different cp process for each one. One way would be to copy then rename them using prename (rename is symlinked to this by default on Debian based distros). Using this and the Linux mktemp:

tmp=$(mktemp -d --tmpdir=.)
cp ABC.* "$tmp"
prename "s:$tmp/ABC:DEF:" "$tmp/"*
rmdir "$tmp"

Update

Actually pax may be a better way to go here:

pax -rws '/^ABC/DEF/' ABC.* .

Unfortunately, despite pax being both POSIX and Linux Standard Base, few distros currently include it by default.


tar will do this for you really fast.

TEST

First I created 2 directories and 10 files:

% mkdir test1 test2 ; cd test1
% for n in `seq 1 10` ; do touch ABC.file$n ; done
% ls

> ABC.file1   ABC.file2  ABC.file4  ABC.file6  ABC.file8
> ABC.file10  ABC.file3  ABC.file5  ABC.file7  ABC.file9

Then I copied them:

% tar -cf - ./* |\ 
    tar -C../test2 --transform='s/ABC/DEF/' -xf -
% ls ../test2

> DEF.file1   DEF.file2  DEF.file4  DEF.file6  DEF.file8
> DEF.file10  DEF.file3  DEF.file5  DEF.file7  DEF.file9

TRANSFORM

So GNU tar will accept a sed --transform=EXPRESSION for file renaming. This can even rename only some of the files. For instance:

% tar -cf - ./* |\ 
    tar -C../test2 --transform='s/ABC\(.*[0-5]\)/DEF\1/' -xf -
% ls ../test2

> ABC.file6  ABC.file8  DEF.file1   DEF.file2  DEF.file4
> ABC.file7  ABC.file9  DEF.file10  DEF.file3  DEF.file5

So that's one advantage.

STREAM

Also consider that this is only two tar processes - and that will not alter regardless of your file count.

tar | tar

tar is as optimized as you could want it to be. This will never have problem argument counts or runaway child processes. This is just A > B done.

ARGUMENTS

I use 7 distinct arguments combined between my two tar processes here. The most important one is listed here first:

- stdout/stdin - this informs tar that it will be streaming either its input or output to or from stdin/stdout which it will interpret correctly depending on whether or not it is building or extracting an archive.

-c create - this tells tar to build the archive. The next argument tar expects is...

-f file - we specify that tar will be working with a file object rather than a tape-device or whatever. And the file it will be working with, as noted above, is stdin/stdout - in other words, our |pipe.

./* all $PWD/files - not too much to explain here except that the archive argument comes first, so - then ./*.

...and on the other side of the |pipe...

-C change directory - this informs tar that it needs to change to the directory I specify before performing any other action, so effectively it just cd ../test2 before extraction.

--transform='s/ed/EXPR/' - as has already been mentioned, this did the renaming. But the docs indicate that it can take any sed expression or //flag.

-x extract - after tar changes to our target directory and receives our renaming instructions we instruct it to begin extracting all of the files into its current directory from the -f - |pipe archive file. No mystery.