将多个文件从文件名 X 复制到文件名 Y?

将多个文件从文件名 X 复制到文件名 Y?

我想做的是复制字典范围内的文件。

文件示例:

-rw-r--r--   1 root root   15276 Oct  5  2004 a2ps.cfg
-rw-r--r--   1 root root    2562 Oct  5  2004 a2ps-site.cfg
-rw-r--r--   4 root root    4096 Feb  2  2007 acpi.txt
-rw-r--r--   1 root root      48 Feb  8  2008 adjtime.jpg
-rw-r--r--   4 root root    4096 Feb  2  2007 alchemist.jpg

使用示例:

  • 将 3 个文件从asps.cfg复制到acpi.txt
  • 将 3 个文件从a2ps-site.cfg复制到adjtime.jpg
  • 将 4 个文件从a2ps-site.cfg复制到alchemist.jpg

那么有没有办法将一系列文件(从文件名 X 到文件名 Y)复制到一个目录中?

喜欢:cp filenameX ... filenameY destination/

答案1

通用方法是定义一个打印一系列文件名的 shell 函数。此函数的简单版本将列出当前目录中两个文件名之间的所有文件:

range()
{
    ls | sed -n "/^$1\$/,/^$2\$/p"
}

这使用 sed 范围来打印两个给定字符串 ($1$2) 之间的任何内容。

然后您可以在cp(1)命令中使用此函数:

cp $(range asps.cfg acpi.txt) /destination/path

如果文件名中含有空格,此操作将会失败。为此,你需要变得更复杂一些:

range asps.cfg acpi.txt | xargs -d '\n' -I {} cp {} /destination/path

如果您的文件名中包含换行符 (\n),则该操作将会失败。这是不太可能的,所以解决这个问题留给读者作为练习。

您可以将其一起放入另一个 shell 函数中:

cprange()
{
    [ $# -eq 3 ] || { echo "usage: cprange start end dir" >&2; return 1;}
    range "$1" "$2" | xargs -d '\n' -I {} cp {} "$3"
}

并像这样使用它:

cprange filenameX filenameY destination

请记住,范围仅适用于当前目录中的文件名。您可以通过多种方式对此进行扩展(向 附加目录参数range、从参数中提取路径到rangeusingdirname等),但我将根据您的要求将其留给您。请在此询问您是否需要更多详细信息。

答案2

Zsh 有一种简单的方法可以从 glob 结果中选择一系列文件(glob 是通配符匹配)。从好的方面来说,该命令编写起来很短。在减号站点上,您必须计算出要写入的文件的序号。例如,以下命令复制.jpg当前目录中第 21 个、第 22 个、…、第 40 个扩展名的文件,文件按字母顺序枚举:

cp *.jpg([21,40]) destination/

Zsh 有一个选项可能对您有帮助,也可能没有帮助:under setopt numeric_glob_sort, foo9bar.jpgwill be sorted before foo10bar.jpg。您还可以在 glob 限定符中选择不同的排序顺序,例如cp *.jpg(om[21,40]) destination/选择第 21 到 40 个最近的文件(使用大写字母O以相反的顺序排序)。看全局限定符在手册中了解更多信息。

在任何 shell 下,您都可以编写一个循环来迭代文件,从要写入的第一个文件开始复制,并在最后一个文件后停止。警告,未经测试。

in_range=
for x in *.jpg; do
  if [ "$x" = "first-file.jpg" ]; then in_range=1; fi
  if [ -n "$in_range" ]; then cp "$x" destination/; fi
  if [ "$x" = "last-file.jpg" ]; then break; fi
done

答案3

此示例中最简单的是使用 M-* 来完成您的模式并删除您不想复制的模式。

% cp *[hit Escape and press *]
->
% cp file1 file2 file3 file4 ... 

然后手动删除您不想复制的文件。无论如何,这是一个 shell 功能,而不是cp的。

您可以根据需要完善该模式。如果目录中有许多其他文件,并且您只想复制以 开头的文件a,则只需以该字母开始模式即可。您可能需要查找有关文件名通配的 shell 文档。例如,http://tldp.org/LDP/abs/html/globbingref.html

答案4

看起来文件名已排序,并且您似乎以相同的数量分发。

将所有文件名保存到一个文件中

ls > all_files

将文件分成批次

split -l 4 all_files all_files-

现在每个文件中有 4 个文件名,all_files-*

选择一个,说出all_files-aa并做你的副本:

xargs -I{} cp {} folder_for_batch_1 < all_files-aa

相关内容