将一组文件 (Filename*) 复制到备份 (Filename*.bak)

Win*_*nix 13 command-line ms-dos cp

背景

在 Linux 中,您可以:

  • 列出一组文件 ls Filename*
  • 删除一组文件 rm Filename*
  • 移动一组文件 mv Filename* /New/Directory
  • 但是你不能复制一组文件:cp Filename* *.bak

更改 Linuxcp命令以复制文件组

我有一组我想复制的文件,而无需逐个输入名称并使用以下cp命令:

$ ls gmail-meta3*
gmail-meta3                          gmail-meta3-REC-1558392194-26467821
gmail-meta3-LAB-1558392194-26467821  gmail-meta3-YAD-1558392194-26467821
Run Code Online (Sandbox Code Playgroud)

我怎样才能使用像旧的 DOS 命令这样的东西copy gmail-meta3* *.bak

我不想输入四次类似的命令:

cp gmail-meta3-LAB-1558392194-26467821 gmail-meta3-LAB-1558392194-26467821.bak
Run Code Online (Sandbox Code Playgroud)

我正在寻找一个脚本/函数/应用程序,它接受旧文件名组和新文件名组的参数,而不是硬编码文件名。例如,用户可以键入:

copy gmail-meta3* *.bak
Run Code Online (Sandbox Code Playgroud)

或者他们可能会输入:

copy gmail-meta3* save-*
Run Code Online (Sandbox Code Playgroud)

cbo*_*jar 15

您可以使用find

find . -max-depth 1 -name 'gmail-meta3*' -exec cp "{}" "{}.bak" \;
Run Code Online (Sandbox Code Playgroud)

这将在当前目录中找到.名称与 glob 模式匹配的所有文件(注意模式周围的单引号以防止 shell globbing)。对于找到的每个文件,它将cp从 name 执行到 name.bak。这 \; 最后确保它会单独处理每个文件,而不是一次传递所有文件。最大深度为 1 仅搜索当前目录而不是向下递归。


pa4*_*080 15

以下是sed适用于此任务的的一种非典型用法示例:

sed -i.bak '' file-prefix*
Run Code Online (Sandbox Code Playgroud)

这样,实际上,sed不会更改文件,因为我们没有提供任何命令'',但是由于该选项,-i[suffix]它会为每个文件创建一个备份副本。我在搜索时发现了这种方法 有没有办法创建文件的备份副本,而无需两次输入其名称?


xio*_*ota 11

您可以将for循环与bash.?一起使用通常,我只会将其输入为单行,因为这不是我经常执行的任务:

for f in test* ; do cp -a "$f" "prefix-${f}.ext" ; done
Run Code Online (Sandbox Code Playgroud)

但是,如果您需要它作为脚本:

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
}
Run Code Online (Sandbox Code Playgroud)

用法类似于 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
Run Code Online (Sandbox Code Playgroud)


ste*_*ver 6

您可能最接近 DOS 范式的是mcp(从mmv包中):

mcp 'gmail-meta3*' 'gmail-meta3#1.bak'
Run Code Online (Sandbox Code Playgroud)

如果zsh可用,它的贡献zmv模块可能更接近:

autoload -U zmv

zmv -C '(gmail-meta3*)' '$1.bak'
Run Code Online (Sandbox Code Playgroud)

ls无论如何都会避免-您自己的答案的变体对空格(包括换行符)是安全的

printf '%s\0' gmail-meta3* | while IFS= read -r -d '' f; do cp -a -- "$f" "$f.bak"; done
Run Code Online (Sandbox Code Playgroud)

也许

printf '%s\0' gmail-meta3* | xargs -0 -I{} cp -a -- {} {}.bak
Run Code Online (Sandbox Code Playgroud)


Rob*_*edl 5

rsync 唯一解决方案

如果你只是想备份你的文件,你可以将它们复制到一个新目录

rsync /path/to/dir/Filename* /path/to/backupdirectory

这会将Filename文件从复制/path/to/dir//path/to/backupdirectory.


rsync + 文件重命名

如果你想让你的备份文件有后缀,事情就会变得棘手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'


Win*_*nix 4

我把这句话写进了我的~/.bashrc. find我想可以发布更好的答案。更好的答案可以用 C 语言编写。希望这个问答能够帮助我们找到更好的答案:

\n\n\n\n
cps () {\n    # cps "Copy Splat", copy group of files to backup, ie "cps Filename .bak"\n    # Copies Filename1 to Filename1.bak, Filename2 to Filename2.bak, etc.\n    # If Filename1.bak exists, don\'t copy it to Filename1.bak.bak\n    for f in "$1"*; do [[ ! "$f" == *"$2" ]] && cp -a "$f" "$f$2"; done\n\n    # OLD version comments suggested to remove \n    # ls "$1"* | while read varname; do cp -a "$varname" "$varname$2"; done\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n
    \n
  • for f in "$1"*; do:$1gmail-meta3参数,f是匹配的文件列表。结合这意味着 gmail-meta3、gmail-meta3-LAB-9999 等执行以下操作
  • \n
  • [[ ! "$f" == *"$2" ]] &&:$f和上面一样f$2.bak传递的参数。结合起来,这意味着如果文件名不以.bak(因为我们不想复制.bak和创建.bak.bak)结尾,则执行以下操作
  • \n
  • cp -a "$f" "$f$2";将 gmail-meta3 复制到 gmail-meta3.bak 等
  • \n
  • done:循环并获取gmail-meta3* 列表中的下一个文件名。
  • \n
\n\n
\n\n

cps gmail-meta3 .bak样本输出

\n\n

这里使用这个问题作为例子来展示它的实际效果:

\n\n
\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\nrick@alien:~/gmail$ ll gmail-meta3*\n-rw-rw-r-- 1 rick rick 26467821 May 20 16:43 gmail-meta3\n-rw-rw-r-- 1 rick rick 26467821 May 20 16:43 gmail-meta3.bak\n-rw-rw-r-- 1 rick rick      643 May 20 16:43 gmail-meta3-LAB-1558392194-26467821\n-rw-rw-r-- 1 rick rick      643 May 20 16:43 gmail-meta3-LAB-1558392194-26467821.bak\n-rw-rw-r-- 1 rick rick    49607 May 20 16:44 gmail-meta3-REC-1558392194-26467821\n-rw-rw-r-- 1 rick rick    49607 May 20 16:44 gmail-meta3-REC-1558392194-26467821.bak\n-rw-rw-r-- 1 rick rick   728954 Jun 27 17:04 gmail-meta3-YAD-1558392194-26467821\n-rw-rw-r-- 1 rick rick   728954 Jun 27 05:46 gmail-meta3-YAD-1558392194-26467821.bak\n\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\nrick@alien:~/gmail$ cps gmail-meta3 .bak\n\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\nrick@alien:~/gmail$ ll gmail-meta3*\n-rw-rw-r-- 1 rick rick 26467821 May 20 16:43 gmail-meta3\n-rw-rw-r-- 1 rick rick 26467821 May 20 16:43 gmail-meta3.bak\n-rw-rw-r-- 1 rick rick      643 May 20 16:43 gmail-meta3-LAB-1558392194-26467821\n-rw-rw-r-- 1 rick rick      643 May 20 16:43 gmail-meta3-LAB-1558392194-26467821.bak\n-rw-rw-r-- 1 rick rick    49607 May 20 16:44 gmail-meta3-REC-1558392194-26467821\n-rw-rw-r-- 1 rick rick    49607 May 20 16:44 gmail-meta3-REC-1558392194-26467821.bak\n-rw-rw-r-- 1 rick rick   728954 Jun 27 17:04 gmail-meta3-YAD-1558392194-26467821\n-rw-rw-r-- 1 rick rick   728954 Jun 27 17:04 gmail-meta3-YAD-1558392194-26467821.bak\n\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\nrick@alien:~/gmail$ \n
Run Code Online (Sandbox Code Playgroud)\n\n

注意:这使用-a带有cp命令的标志来保留时间戳并让您更好地掌握文件备份。

\n\n

请注意文件副本如何与原始文件具有完全相同的日期和时间。如果-a省略该参数,则会为它们提供当前日期和时间,并且看起来不像真正的备份,只是文件大小相同。

\n

  • 人们不是总是建议不要解析 `ls` (7认同)
  • 既然您提到“find”,我假设您意识到解析“ls”的危险?但在你的情况下,两者都不是必要的:只需执行`for file in "$1"*; 复制 -a "$file" "$file$2"; done` — 这是完全安全的,并且比通过 `ls` 或 `find` 和 `while` 循环进行的任何类型的间接寻址要简单得多。 (3认同)