根据名称将文件复制到多个文件夹中

根据名称将文件复制到多个文件夹中

我有多层嵌套的文件夹,名称如x/y/z/Drawingsa/b/c/x/y/z/Plans。可能有数百个上层文件夹在其路径中的某个位置包含一个文件夹DrawingsPlans子文件夹。

然后我有名为Drawings.jpg和 的图标Plans.jpg。我想将正确的 JPG 复制到所有正确的(即相应命名的)子文件夹中。也就是说,对于每个../Drawings文件夹,无论它位于文件夹层次结构中的哪个位置,我都希望看到一个../Drawings/Drawings.jpg, 和一个../Plans/Plans.jpg文件。

我在 Ubuntu 上运行,但我想不出将名为 的文件复制Whatever.jpg到每个名为 的子文件夹中的方法something/something/Whatever。问题基本上是根据文件夹名称将单个文件源复制到多个目标之一。

需要妥善存放的 JPG 很可能不会超过 15 个,但每个 JPG 都有数百个可能的目标子文件夹。

我可以使用一系列简单的cp命令来实现此目的吗?或者一些可以产生所需结果的 Bash 脚本?

答案1

由于您很乐意将非叶目录视为复制命令的候选目录,因此您可以将解决方案基于find.

iconDir=/path/to/icons_directory
rootDir=/path/to/top/of/drawings_projects_etc

find "$rootDir" -type d -exec sh -c '
    iconDir="$0"
    for thisDir in "$@"
    do
        iconName="${thisDir##*/}.jpg"
        [ -f "$iconDir/$iconName" ] && echo cp -p "$iconDir/$iconName" "$thisDir"
    done
' "$iconDir" {} +

$rootDir这样做的作用是依次考虑下面的每个目录。它会在$iconDir目录路径最后一部分(后缀为 )对应的位置查找图标文件.jpg,如果找到,则将其复制到目标目录。

正如所写,您只会得到一份预期行动的声明。删除echo前缀cp以使其实际复制文件。

我使用cp -p而不是cp保留权限和 - 通常更有用 - 原始文件的时间戳。如果您$iconDir和您的所有$rootDir树都位于同一文件系统上,您可能更喜欢使用ln而不是cp -p.

答案2

zsh

for icon (path/to/icons/*.jpg(N.))
  for dir (path/to/dirs/**/$icon:t:r(N/))
    cp $icon $dir/

为了加快速度,您可以进行许多优化:

  • 首先构建所有目录的列表并重用它,这样就不必path/to/dirs为每个图标爬行目录树
  • makebuiltincp可以消除分叉进程并为每个副本执行外部命令的成本
  • 不要Noglob 进行排序,因为我们实际上并不需要在这里对它们进行排序。
  • 禁用多字节字符支持,因为在这里进行字节到字节的比较就足够了。

所以

zmodload zsh/files
set +o multibyte
dirs=(path/to/dirs/**/*(N/oN))
for icon (path/to/icons/*.jpg(N.oN))
  for dir (${(M)dirs:#*/$icon:t:r})
    cp $icon $dir/

(其中,最重要的是zmodload zsh/files启用内置cp)。

您可能想要使用lnor ln -sr-r是 GNU 扩展,但不被zsh的内置支持ln)而不是cp创建链接而不是副本以节省空间。

相关内容