В Linux вы можете:
ls Filename*
rm Filename*
mv Filename* /New/Directory
cp Filename* *.bak
cp
команда для копирования группы файлов У меня есть группа файлов, которые я хотел бы скопировать, не вводя имена по одному и используя команду cp
:
$ ls gmail-meta3*
gmail-meta3 gmail-meta3-REC-1558392194-26467821
gmail-meta3-LAB-1558392194-26467821 gmail-meta3-YAD-1558392194-26467821
Как я могу использовать что-то вроде старой команды DOS copy gmail-meta3* *.bak
?
Я не хочу вводить подобную команду четыре раза:
cp gmail-meta3-LAB-1558392194-26467821 gmail-meta3-LAB-1558392194-26467821.bak
Я ищу скрипт / функцию / приложение, которое принимает параметры для старой и новой группы имен файлов, а не что-то с жестко закодированными именами файлов. Например, пользователь может ввести:
copy gmail-meta3* *.bak
или они могут ввести:
copy gmail-meta3* save-*
Вы можете использовать find
:
find . -max-depth 1 -name 'gmail-meta3*' -exec cp "{}" "{}.bak" \;
. Он найдет в текущем каталоге .
все файлы с именем, совпадающим с шаблоном glob (обратите внимание на одинарные кавычки вокруг шаблона, чтобы предотвратить слипание оболочки ). Для каждого найденного файла он будет выполнять cp
от имени к имени. \; в конце гарантирует, что он будет делать каждый файл отдельно, а не передавать их все сразу. Максимальная глубина, равная 1, выполняет поиск только в текущем каталоге, а не в обратном направлении.
Еще один способ выполнить ваше требование - скопировать файлы во временный каталог и использовать команду rename
для их переименования.
$ mkdir backup
$ cp filename* /tmp/rename-backup/
$ rename 's/(filename.*)/$1.bak/' /tmp/rename-backup/*
$ mv /tmp/rename-backup/* ./
Если вам нужен сценарий, вы можете использовать его примерно так
cps () {
mkdir -p /tmp/rename-backup/
cp "$1"* /tmp/rename-backup/
rename "s/($1.*)/\$1.$2/" /tmp/rename-backup/*
mv "/tmp/rename-backup/$1"*".$2" .
}
И можете использовать его так:
cps file bak
Это пример
$ ls -l
total 0
-rw-r--r-- 1 danny danny 0 Jun 26 16:23 file a
-rw-r--r-- 1 danny danny 0 Jun 26 16:23 file ab
-rw-r--r-- 1 danny danny 0 Jun 26 16:23 file ac
-rw-r--r-- 1 danny danny 0 Jun 26 16:05 filename1
-rw-r--r-- 1 danny danny 0 Jun 26 16:05 filename2
-rw-r--r-- 1 danny danny 0 Jun 26 16:05 filename3
-rw-r--r-- 1 danny danny 0 Jun 26 16:05 filename4
$ cps file bak
$ ls -l
total 0
-rw-r--r-- 1 danny danny 0 Jun 26 16:23 file a
-rw-r--r-- 1 danny danny 0 Jun 26 16:41 file a.bak
-rw-r--r-- 1 danny danny 0 Jun 26 16:23 file ab
-rw-r--r-- 1 danny danny 0 Jun 26 16:41 file ab.bak
-rw-r--r-- 1 danny danny 0 Jun 26 16:23 file ac
-rw-r--r-- 1 danny danny 0 Jun 26 16:41 file ac.bak
-rw-r--r-- 1 danny danny 0 Jun 26 16:05 filename1
-rw-r--r-- 1 danny danny 0 Jun 26 16:41 filename1.bak
-rw-r--r-- 1 danny danny 0 Jun 26 16:05 filename2
-rw-r--r-- 1 danny danny 0 Jun 26 16:41 filename2.bak
-rw-r--r-- 1 danny danny 0 Jun 26 16:05 filename3
-rw-r--r-- 1 danny wheel 0 Jun 26 16:41 filename3.bak
-rw-r--r-- 1 danny danny 0 Jun 26 16:05 filename4
-rw-r--r-- 1 danny danny 0 Jun 26 16:41 filename4.bak
rsync only solution
Если вы просто хотите сделать резервную копию своих файлов, вы можете скопировать их в новый каталог
rsync /path/to/dir/Filename* /path/to/backupdirectory
Это скопирует файлы Filename
из /path/to/dir/
в /path/to/backupdirectory
.
rsync + filerename
Если вы хотите, чтобы у ваших файлов резервных копий был суффикс, все становится хакерским с rsync
...
rsync -Iu /path/to/dir/Filename* /path/to/dir/Filename* -b --backup-dir=/path/to/backupdirectory --suffix=.bak
Это перезапишет существующие файлы ... существующими файлами (-I
), но только если они (-u
) новее (чем они не являются) и создают резервная копия с суффиксом.
Вы также можете сделать это в том же каталоге. Но лучше исключить существующие резервные копии.
rsync -Iu /path/to/dir/Filename* /path/to/dir/Filename* -b --backup-dir=/path/to/backupdirectory --suffix=.bak --exclude '*.bak'
Ближайшая парадигма DOS, которую вы, скорее всего, получите, - mcp
(из пакета mmv
):
mcp 'gmail-meta3*' 'gmail-meta3#1.bak'
Если доступно zsh
, его добавленный модуль zmv
, возможно, немного ближе:
autoload -U zmv
zmv -C '(gmail-meta3*)' '$1.bak'
Я бы избегал ls
вне зависимости - вариант вашего собственного ответа , который безопасен для пробелов (включая переводы строк), будет
printf '%s\0' gmail-meta3* | while IFS= read -r -d '' f; do cp -a -- "$f" "$f.bak"; done
или, возможно,
printf '%s\0' gmail-meta3* | xargs -0 -I{} cp -a -- {} {}.bak
Это следует сделать в соответствии с просьбой:
cps(){ p="${@: -1}"; for f in "${@:1:$#-1}"; do cp -ai "$f" "${p//\?/$f}"; done }
Использование:
cps FILES... pattern
Example 1: cps gmail-meta3* ?.bak
Example 2: cps * save-?
Example 3: cps * bla-?-blubb
Я выбрал ?
, потому что #
необходимо заключать в кавычки, когда это первый символ шаблона, в противном случае он распознается как начало комментария.
Тест:
$ touch 'test};{bla#?"blubb'
$ cps test* bla-?-blubb
$ ls
test};{bla#?"blubb bla-test};{bla#?"blubb-blubb
Некоторые более ранние версии скрипта для добавления суффикса:
Похоже на ответ @ WinEunuuchs2Unix, но я считаю более гибким и не разбирает ls
:
cps(){ S="$1"; shift; printf '%s\0' "$@" | xargs -0 -I{} cp -abfS "$S" {} {}; }
Поместите это в свой .bashrc
.
Использование:
cps SUFFIX FILES...
Example: cps .bak gmail-meta3*
Альтернатива, с суффиксом в качестве последнего аргумента ( через и через ):
cps(){ S="${@: -1}"; printf '%s\0' "${@:1:$#-1}" | xargs -0 -I{} cp -abfS "$S" {} {}; }
Использование:
cps FILES... SUFFIX
Example: cps gmail-meta3* .bak
<час> Вы можете использовать петлю for
с bash
. Как правило, я просто набрал бы его как однострочное, потому что это не та задача, которую я часто выполняю:
for f in test* ; do cp -a "$f" "prefix-${f}.ext" ; done
Однако, если вам нужно это как скрипт:
cps() {
[ $# -lt 2 ] && echo "Usage: cps REGEXP FILES..." && return 1
PATTERN="$1" ; shift
for file in "$@" ; do
file_dirname=`dirname "$file"`
file_name=`basename "$file"`
file_newname=`echo "$file_name" | sed "$PATTERN"`
if [[ -f "$file" ]] && [[ ! -e "${file_dirname}/${file_newname}" ]] ; then
cp -a "$file" "${file_dirname}/${file_newname}"
else
echo "Error: $file -> ${file_dirname}/${file_newname}"
fi
done
}
Использование аналогично rename
. Для проверки:
pushd /tmp
mkdir tmp2
touch tmp2/test{001..100} # create test files
ls tmp2
cps 's@^@prefix-@ ; s@$@.bak@' tmp2/test* # create backups
cps 's@$@.bak@' tmp2/test* # more backups ... will display errors
ls tmp2
\rm -r tmp2 # cleanup
popd
Я написал эту однострочную в мой ~/.bashrc
. Полагаю, гораздо лучшие ответы с использованием find
можно опубликовать. Еще лучшие ответы могут быть написаны на языке C. Надеюсь, что этот Q & amp; A заставляет шарик катиться за лучшие ответы:
cps () {
# cps "Copy Splat", copy group of files to backup, ie "cps Filename .bak"
# Copies Filename1 to Filename1.bak, Filename2 to Filename2.bak, etc.
# If Filename1.bak exists, don't copy it to Filename1.bak.bak
for f in "$1"*; do [[ ! "$f" == *"$2" ]] && cp -a "$f" "$f$2"; done
# OLD version comments suggested to remove
# ls "$1"* | while read varname; do cp -a "$varname" "$varname$2"; done
}
for f in "$1"*; do
: $1
- параметр gmail-meta3
и f
- список подходящих файлов. В сочетании это означает, что gmail-meta3, gmail-meta3-LAB-9999 и т. Д. Делают следующее [[ ! "$f" == *"$2" ]] &&
: $f
совпадает с f
выше. $2
- это переданный параметр .bak
. В сочетании это означает, что если имя файла не заканчивается на .bak
(потому что мы не хотим копировать .bak
и создавать .bak.bak
), тогда выполните следующее cp -a "$f" "$f$2";
, скопируйте gmail-meta3 в gmail-meta3.bak и т. д. done
: вернуться назад и получить следующее имя файла в списке gmail-meta3
*. cps gmail-meta3 .bak
Пример выходных данных Используя вопрос в качестве примера, вот как он выглядит в действии:
───────────────────────────────────────────────────────────────────────────────────────────
rick@alien:~/gmail$ ll gmail-meta3*
-rw-rw-r-- 1 rick rick 26467821 May 20 16:43 gmail-meta3
-rw-rw-r-- 1 rick rick 26467821 May 20 16:43 gmail-meta3.bak
-rw-rw-r-- 1 rick rick 643 May 20 16:43 gmail-meta3-LAB-1558392194-26467821
-rw-rw-r-- 1 rick rick 643 May 20 16:43 gmail-meta3-LAB-1558392194-26467821.bak
-rw-rw-r-- 1 rick rick 49607 May 20 16:44 gmail-meta3-REC-1558392194-26467821
-rw-rw-r-- 1 rick rick 49607 May 20 16:44 gmail-meta3-REC-1558392194-26467821.bak
-rw-rw-r-- 1 rick rick 728954 Jun 27 17:04 gmail-meta3-YAD-1558392194-26467821
-rw-rw-r-- 1 rick rick 728954 Jun 27 05:46 gmail-meta3-YAD-1558392194-26467821.bak
───────────────────────────────────────────────────────────────────────────────────────────
rick@alien:~/gmail$ cps gmail-meta3 .bak
───────────────────────────────────────────────────────────────────────────────────────────
rick@alien:~/gmail$ ll gmail-meta3*
-rw-rw-r-- 1 rick rick 26467821 May 20 16:43 gmail-meta3
-rw-rw-r-- 1 rick rick 26467821 May 20 16:43 gmail-meta3.bak
-rw-rw-r-- 1 rick rick 643 May 20 16:43 gmail-meta3-LAB-1558392194-26467821
-rw-rw-r-- 1 rick rick 643 May 20 16:43 gmail-meta3-LAB-1558392194-26467821.bak
-rw-rw-r-- 1 rick rick 49607 May 20 16:44 gmail-meta3-REC-1558392194-26467821
-rw-rw-r-- 1 rick rick 49607 May 20 16:44 gmail-meta3-REC-1558392194-26467821.bak
-rw-rw-r-- 1 rick rick 728954 Jun 27 17:04 gmail-meta3-YAD-1558392194-26467821
-rw-rw-r-- 1 rick rick 728954 Jun 27 17:04 gmail-meta3-YAD-1558392194-26467821.bak
───────────────────────────────────────────────────────────────────────────────────────────
rick@alien:~/gmail$
Примечание: При этом используется флаг -a
с командой cp
для сохранения временных отметок и лучшего понимания ваших резервных копий файлов.
Обратите внимание, что копии файлов имеют ту же дату и время, что и оригиналы. Если параметр -a
не указан, им будут даны текущая дата и время, и он не будет выглядеть как настоящая резервная копия, за исключением того, что размер файла будет таким же.
Вот пример одного нетипичного использования sed
, применимого для этой задачи:
sed -i.bak '' file-prefix*
Таким образом, фактически, sed
не будет изменять файлы, потому что мы не не предоставил никаких команд ''
, но благодаря опции -i[suffix]
он создаст резервную копию каждого файла. Я нашел этот подход, когда искал Есть ли способ создать резервную копию файла, не вводя его имя дважды?