我有多层嵌套的文件夹,名称如x/y/z/Drawings
和a/b/c/x/y/z/Plans
。可能有数百个上层文件夹在其路径中的某个位置包含一个文件夹Drawings
或Plans
子文件夹。
然后我有名为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
为每个图标爬行目录树 - makebuiltin
cp
可以消除分叉进程并为每个副本执行外部命令的成本 - 不要
N
对o
glob 进行排序,因为我们实际上并不需要在这里对它们进行排序。 - 禁用多字节字符支持,因为在这里进行字节到字节的比较就足够了。
所以
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
)。
您可能想要使用ln
or ln -sr
(-r
是 GNU 扩展,但不被zsh
的内置支持ln
)而不是cp
创建链接而不是副本以节省空间。