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 informstar
that it will be streaming either its input or output to or fromstdin/stdout
which it will interpret correctly depending on whether or not it is building or extracting an archive.
-c
create - this tellstar
to build the archive. The next argumenttar
expects is...
-f
file - we specify thattar
will be working with afile
object rather than a tape-device or whatever. And the file it will be working with, as noted above, isstdin/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 informstar
that it needs to change to the directory I specify before performing any other action, so effectively it justcd ../test2
before extraction.
--transform='s/ed/EXPR/'
- as has already been mentioned, this did the renaming. But the docs indicate that it can take anysed
expression or//flag
.
-x
extract - aftertar
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.