GNU/Linux下zip命令正确用法:展平子目录结构
解决GNU/Linux下zip压缩指定文件并展平目录结构的问题
目录结构回顾
当前工作目录为~/Documents,目标文件路径:
~/Documents/foo1/foo2/foo3a/foo4/*.txt ~/Documents/foo1/foo2/foo3b/foo4/*.txt
需求1:压缩后保留foo3a/foo4/xxx.txt这类路径(去掉foo1/foo2/前缀)
命令实现
在~/Documents目录下执行:
zip -r foo.zip -C foo1/foo2 . -i "*/foo4/*.txt"
参数解释
-C foo1/foo2:临时将工作目录切换到foo1/foo2,压缩时以此目录为基准生成路径-r:递归遍历目录-i "*/foo4/*.txt":只匹配所有子目录下foo4文件夹中的.txt文件
这样生成的foo.zip内部路径会从foo3a/foo4/、foo3b/foo4/开始,正好符合需求。
需求2:压缩后将foo4目录合并到上级,即foo3a/xxx.txt这类路径
命令实现(方法一:利用zip内置参数)
在~/Documents目录下执行:
zip -r foo.zip -C foo1/foo2 */foo4/*.txt -j "*/"
参数解释
-C foo1/foo2:同样切换到目标基准目录-j "*/":对每个foo3a、foo3b目录,压缩时去掉其直接子目录(即foo4),将foo4内的.txt文件直接放到foo3a、foo3b目录下
命令实现(方法二:结合find+sed处理路径)
如果zip版本不支持-j的目录参数,可使用以下命令:
find foo1/foo2 -name "*.txt" -path "*foo4/*" | sed 's/foo1\/foo2\/\([^\/]*\)\/foo4\/\(.*\)/\1\/\2/' | zip foo.zip -@
参数解释
find:找出所有符合条件的.txt文件sed:将路径中的foo1/foo2/xxx/foo4/yyy.txt替换为xxx/yyy.txtzip -@:从标准输入读取需要压缩的文件路径列表,生成对应结构的压缩包
你之前命令的问题分析
- 前两个命令未使用
-C切换基准目录,所以zip会保留从当前目录(~/Documents)开始的完整路径,导致出现foo1/foo2/前缀 - 第三个命令使用
-rj时,-j会去掉所有目录结构,同时-i的路径过滤是基于原始路径的,两者结合导致zip无法正确匹配到文件,最终生成空压缩包
内容的提问来源于stack exchange,提问作者MW2023
相关产品推荐
相关产品推荐

