三级目录结构下批量将sub-2文件夹中JPG文件复制到对应sub-1文件夹的脚本问题及解决方案咨询
问题分析与解决方案
为什么你的现有脚本无法正常工作?
第一个脚本(逐个进入sub-1执行)
你在sub-1目录下运行的find . -type f -name "*.jpg" -exec cp {} ./ \;其实逻辑上能把sub-2里的图片复制到sub-1,但可能因为这些原因让你觉得“失效”:
- 文件名重复覆盖:如果不同sub-2里有重名的JPG,后复制的文件会直接覆盖先复制的,若你没留意覆盖提示,会误以为脚本没生效;
- 重复复制自身:第一次执行后sub-1里已经有JPG,再次运行脚本时,
find会同时找到sub-1和sub-2里的JPG,尝试把sub-1里的文件复制到自身,触发cp的错误提示(比如cp: './xxx.jpg' and './xxx.jpg' are the same file),干扰你的判断; - 视觉混淆:如果sub-1目录文件很多,你可能没注意到新复制进来的JPG文件。
第二个脚本(尝试从main目录执行)
这个脚本的核心问题是**find的-exec命令是在你启动find的工作目录(也就是main)下执行的**,而不是在文件所在的sub-2目录:
- 当你用
../作为目标路径时,它指向的是main目录的父目录?不对——实际是,如果你在sub-1目录下执行这个脚本,../刚好指向main,自然所有图片都跑到main里去了;如果在main目录执行,../会指向main的上级目录,结果更不符合预期。
从main目录一键完成复制的方法
我们需要让每个JPG文件都被复制到它所在的sub-2的父目录(也就是对应的sub-1),这里有几种简单可靠的方法:
方法1:用find的-execdir(最推荐)
-execdir和-exec的区别是,它会切换到找到文件的所在目录再执行命令,完美解决相对路径的问题:
find main -type f -name "*.jpg" -execdir cp {} .. \;
find main:从main目录开始遍历所有子目录;-execdir cp {} .. \;:在JPG所在的sub-2目录下执行复制,..就是sub-2的父目录(也就是你要的sub-1)。
如果担心重名文件被覆盖,可以加上-n参数(不覆盖已存在的文件):
find main -type f -name "*.jpg" -execdir cp -n {} .. \;
方法2:用dirname手动获取父目录(兼容老旧系统)
如果你的系统不支持-execdir(比如部分老式Unix),可以用dirname来逐层获取父目录:
find main -type f -name "*.jpg" -exec sh -c 'cp "$0" "$(dirname "$(dirname "$0")")"' {} \;
dirname "$0":获取JPG文件所在的sub-2目录;dirname "$(dirname "$0")":进一步获取sub-2的父目录sub-1;- 最终把每个JPG复制到对应的sub-1目录。
方法3:用rsync(适合大量文件)
如果你安装了rsync,这个方法更高效,尤其当你有上万张图片时:
rsync -av --include="*/" --include="*.jpg" --exclude="*" main/ main/
-av:归档模式(保留文件属性)+ 显示详细同步信息;--include="*/":确保rsync能遍历到所有sub-2目录;--include="*.jpg":只处理JPG文件;--exclude="*":排除其他所有非目标文件;main/ main/:源和目标都设为main目录,rsync会自动把sub-2里的JPG同步到它们的父目录sub-1中。
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

