Background
In Linux you can:
- List a group of files with
ls Filename*
- Remove a group of files with
rm Filename*
- Move a group of files with
mv Filename* /New/Directory
- But you cannot copy a group of files with:
cp Filename* *.bak
Change Linux cp
command to copy group of files
I have a group of files I'd like to copy without entering the names one by one and using the cp
command:
$ ls gmail-meta3*
gmail-meta3 gmail-meta3-REC-1558392194-26467821
gmail-meta3-LAB-1558392194-26467821 gmail-meta3-YAD-1558392194-26467821
How can I use something like the old DOS command copy gmail-meta3* *.bak
?
I don't want to type similar command four times:
cp gmail-meta3-LAB-1558392194-26467821 gmail-meta3-LAB-1558392194-26467821.bak
I'm looking for a script/function/app that accepts parameters for old and new filename group and not something with hard-coded filenames. For example, a user can type:
copy gmail-meta3* *.bak
or they might type:
copy gmail-meta3* save-*
Here is an example of one atypical usage of
sed
, that is applicable for this task:In this way, actually,
sed
will not change the files, because we didn't provided any commands''
, but due to the option-i[suffix]
it will create a backup copy of each file. I found this approach when I was searching Is there any way to create backup copy of a file, without type its name twice?You can use
find
:That will find in the current directory
.
all files with a name matching the glob pattern (mind the single quotes around the pattern to prevent shell globbing). For each file found, it will execcp
from name to name.bak. The \; at the end ensures it will do each file individually instead of passing all of them at once. The max depth as 1 only searches the cuurent directory instead of recursing down.You can use a
for
loop withbash
. Normally, I would just type it as a one-liner because this isn't a task I perform often:However, if you need it as a script:
Usage is similar to
rename
. To test:The closest you will likely get to the DOS paradigm is
mcp
(from themmv
package):If
zsh
is available, its contributedzmv
module is perhaps a little closer:I'd avoid
ls
regardless - a variant on your own answer that's safe for whitespace (including newlines) would beor perhaps
rsync only solution
If you just want to backup your files, you can copy them to a new directory
rsync /path/to/dir/Filename* /path/to/backupdirectory
This will copy the
Filename
files from/path/to/dir/
to/path/to/backupdirectory
.rsync + filerename
If you want your backup files to have a suffix, things get hacky with
rsync
...rsync -Iu /path/to/dir/Filename* /path/to/dir/Filename* -b --backup-dir=/path/to/backupdirectory --suffix=.bak
This would overwrite the existing files... with the existing files (
-I
) but only if they are (-u
) newer (which they aren't) and creating a backup, with a suffix.You can also do that in the same directory. But better exclude existing backups.
rsync -Iu /path/to/dir/Filename* /path/to/dir/Filename* -b --backup-dir=/path/to/backupdirectory --suffix=.bak --exclude '*.bak'
I wrote this one-liner into my
~/.bashrc
. Much better answers usingfind
can be posted I suppose. Even better answers could be written in in C. Hopefully this Q&A gets the ball rolling for better answers:for f in "$1"*; do
:$1
is thegmail-meta3
parameter andf
is the list of files matching. Combined this means for gmail-meta3, gmail-meta3-LAB-9999, etc. do the following[[ ! "$f" == *"$2" ]] &&
:$f
is the same asf
above.$2
is the.bak
parameter passed. Combined this means if the filename doesn't end in.bak
(because we don't want to copy.bak
and create.bak.bak
) then do the followingcp -a "$f" "$f$2";
copy gmail-meta3 to gmail-meta3.bak, etc.done
: loop back and grab next filename ingmail-meta3
* list.cps gmail-meta3 .bak
Sample OutputUsing the question as an example here is how it looks in action:
Note: This uses the
-a
flag with thecp
command to preserve timestamps and give you better grasp of your file backups.Notice how the file copies have the exact same date and time as the originals. If the
-a
parameter was omitted they would be given the current date and time and wouldn't look like a true backup except that the file size would be the same.This one should do as requested:
Usage:
I chose
?
because#
must be quoted when it's the first character of pattern, otherwise it's recognized as the start of a comment.Test:
Some earlier versions of the script for adding a suffix:
Similar to @WinEunuuchs2Unix answer, but I think more flexible and not parsing
ls
:Put this in your
.bashrc
.Usage:
Alternative, with the suffix as last argument (via and via):
Usage:
Another method of achieving your requirement is to copy the files to a temporary directory and use the
rename
command to rename them.If you need it as a script, you can use it like so
And you can use it like so:
This is an example