Bash中如何使用find查找指定目录并正确执行zip批量压缩
报错原因
原命令执行失败核心源于两点:
find的-exec参数默认直接调用外部命令,不会触发shell的通配符展开逻辑,写法中的{}/*.*会被作为字面字符串传递给zip,而zip本身不解析shell通配符,无法匹配到对应文件,因此抛出name not matched错误。- 若匹配到的
archive*目录下没有符合*.*规则的文件,zip找不到可压缩的有效内容,就会抛出Nothing to do!报错。
实现方案
以下两种方案都完全符合需求:保持和手动单目录压缩一致的包内路径结构、不使用-r递归参数、不会把空目录纳入压缩包。
方案1:基于find的实现(适配原有写法逻辑)
先切换到目标父目录,执行以下命令:
cd /mydir/moredirs find * -type d -name "archive*" -exec bash -c ' shopt -s nullglob for dir in "$@"; do file_list=("$dir"/*.*) [ ${#file_list[@]} -gt 0 ] && zip ~/"$dir".zip "${file_list[@]}" done ' bash {} +
关键逻辑说明:
- 通过
bash -c启动子shell处理通配符展开,解决find原生-exec不解析通配符的问题 shopt -s nullglob配置表示:如果通配符没有匹配到任何文件,会展开为空值,不会把字面的*.*传给zip- 执行zip前先判断当前目录下是否存在匹配
*.*的文件,只有存在有效文件时才执行压缩,避免空目录触发zip报错 - 用
{} +批量传递匹配到的目录给子shell,执行效率比逐目录调用\;更高 - 压缩完成后,
~/archivethis1.zip包内的文件路径就是archivethis1/文件名.后缀,和手动执行单目录压缩的结构完全一致。
方案2:纯shell循环实现(写法更简洁)
如果不需要复杂的find匹配规则,直接用shell通配符匹配逻辑更简单:
cd /mydir/moredirs shopt -s nullglob for dir in archive*/; do file_list=("$dir"*.*) [ ${#file_list[@]} -gt 0 ] && zip ~/"${dir%/}".zip "${file_list[@]}" done
关键逻辑说明:
archive*/直接匹配当前工作目录下所有以archive开头的子目录,不需要额外调用find${dir%/}用于去掉目录名末尾自动带的斜杠,避免生成的zip文件名出现多余斜杠- 其余空判断、通配符展开逻辑和方案1一致,最终压缩效果完全相同。
内容的提问来源于stack exchange,提问作者PaulM
相关产品推荐
相关产品推荐

