我有一个包含几个子目录的目录。有一个关于压缩文件的问题,其中包含一个我为满足我的需要而稍作修改的答案。
for i in */; do zip "zips/${i%/}.zip" "$i*.csv"; done
但是,我遇到了一个奇怪的问题。对于第一组文件夹(zips/<name>.zip
不存在的文件夹),出现此错误:
zip error: Nothing to do! (zips/2014-10.zip)
zip warning: name not matched: 2014-11/*.csv
但是,当我只是echo
zip语句时:
for i in */; do echo zip "zips/${i%/}.zip" "$i*.csv"; done
然后运行echoed命令(zip zips/2014-10.zip 2014-10/*.csv
),它可以正常工作并压缩文件夹。然后有趣的是,原始命令的后续运行实际上将压缩第一次无法使用的文件夹!
要自己测试此行为:
cd /tmp
mkdir -p 2016-01 2016-02 2016-03 zips
for i in 2*/; do touch "$i"/one.csv; done
for i in 2*/; do touch "$i"/two.csv; done
zip zips/2016-03.zip 2016-03/*.csv
for i in 2*/; do echo zip "zips/${i%/}.zip" "$i*.csv"; done
for i in 2*/; do zip "zips/${i%/}.zip" "$i*.csv"; done
您将看到echo显示以下语句:
zip zips/2016-01.zip 2016-01/*.csv
zip zips/2016-02.zip 2016-02/*.csv
zip zips/2016-03.zip 2016-03/*.csv
但是,实际的zip命令会告诉您:
zip warning: name not matched: 2016-01/*.csv
zip error: Nothing to do! (zips/2016-01.zip)
zip warning: name not matched: 2016-02/*.csv
zip error: Nothing to do! (zips/2016-02.zip)
updating: 2016-03/one.csv (stored 0%)
updating: 2016-03/two.csv (stored 0%)
因此,它实际上是使用zip文件.csv
所在的s更新zip文件,而不是在创建zip文件时更新。并且,如果您复制其中一个zip命令:
$ zip zips/2016-02.zip 2016-02/*.csv
adding: 2016-02/one.csv (stored 0%)
adding: 2016-02/two.csv (stored 0%)
然后重新运行所有内容:
for i in 2*/; do zip "zips/${i%/}.zip" "$i*.csv"; done
您会看到它为2016-02
和更新2016-03
。这是我的输出tree
:
.
├── 2016-01
│ ├── one.csv
│ └── two.csv
├── 2016-02
│ ├── one.csv
│ └── two.csv
├── 2016-03
│ ├── one.csv
│ └── two.csv
└── zips
├── 2016-02.zip
└── 2016-03.zip
另外,(出乎意料的是)这很好用:
zsh -c "$(for i in 2*/; do echo zip "zips/${i%/}.zip" "$i*.csv"; done)"
我在这里做错了什么?(请注意,如果有任何区别,我使用的是zsh而不是bash)
周围的引号"$i*.csv"
会有所不同。Shell用引号将字符串扩展为“ 2014-11 / *。csv”。该确切文件不存在,并zip
报告错误。不带引号的,*
也将扩展(通过文件名扩展/“ globbing”),并且得到的zip
命令是匹配文件的完整列表,每个文件均作为单独的参数。您可以在for
循环内获得第二个行为:
for i in */ ; do zip "zips/${i%/}.zip" "$i"*.csv ; done
zip
也可以自行扩展通配符,但并非在所有情况下都可以。从zip手册中:
该压缩程序可以做的名字是在同一个匹配的zip压缩文件被修改,或在的情况下,-x(排除)或-i(包含)选项,文件列表上进行操作时,通过使用反斜杠或引号告诉外壳程序不要进行名称扩展。
成功创建档案后,原始命令可用于后续尝试,因为zip
尝试将通配符与现有档案的内容进行匹配。它们存在于此,并且仍然存在于文件系统上,因此通过进行报告updating:
。
要zip
在创建存档时处理通配符,请使用-r
(递归)选项递归到请求的目录中,并使用-i
(包含)将其限制为与模式匹配的文件:
for i in */ ; do zip -r "zips/${i%/}.zip" "$i" -i '*.csv' ; done
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句