如何查找文件列表并将它们压缩到单个 zip 文件中?

如何查找文件列表并将它们压缩到单个 zip 文件中?

我想收集我在项目中使用过的所有文件。我正在使用find命令,我希望它找到文件列表,然后将其结果传递给 zip 命令以创建包含所有匹配文件的单个 zip 文件。如果可能的话,只是一个方便。然而,它似乎有问题并且不起作用。

find /lmms/samples/ -name warp01*,JR_effect2k*,clean_low_key*,q_kick_2*,sticky_q_kick*,upright_bass*,pizzi*,chorded_perc*,Tr77_kick*,Tr77_tom1*,Tr77_cym*,hihat_008a*,Hat_o.ds,Hat_c.ds,Kickhard.ds,Tr77_snare* -exec zip {} ~/Desktop/files.zip

输出是:

find: missing argument to `-exec'

附言。

在修复了以下答案中指出的一些错误并遵循其指南后,我重新格式化了代码,如下所示:

find ~/lmms/samples/ (-name warp01* -o -name JR_effect2k* -or -name clean_low_key* -or -name q_kick_2* -or -name sticky_q_kick* -or -name upright_bass*-or  -name pizzi* -or -name chorded_perc* -or -name Tr77_kick* -or -name Tr77_tom1* -or -name Tr77_cym* -or -name hihat_008a* -or -name Hat_o.ds -or -name Hat_c.ds -or -name Kickhard.ds -or  -name Tr77_snare*)  -exec zip -add  ~/Desktop/files.zip {} +

它仍然失败并显示消息bash: syntax error near unexpected token(' `

删除括号可以消除错误,但似乎只向存档中添加一个文件,令人惊讶的是,我似乎在桌面上找不到这一文件!

 find ~/lmms/samples/ -name warp01* -o -name JR_effect2k* -or -name clean_low_key* -or -name q_kick_2* -or -name sticky_q_kick* -or -name upright_bass*-or  -name pizzi* -or -name chorded_perc* -or -name Tr77_kick* -or -name Tr77_tom1* -or -name Tr77_cym* -or -name hihat_008a* -or -name Hat_o.ds -or -name Hat_c.ds -or -name Kickhard.ds -or  -name Tr77_snare*  -exec zip  ~/Desktop/files.zip {} +
  adding: home/john/lmms/samples/drumsynth/tr77/Tr77_snare.ds (deflated 49%)

答案1

-exec需要两个参数:要执行的命令,以及一个标志,用于指示find该命令是每次匹配运行一次 ( ;) 还是每次运行使用尽可能多的文件 ( +)。

另外,zip参数的方向也是错误的。

测试-name也不是这样的。一次只需要一种模式。如果要检查多个模式,则需要使用(“或”)-name组合使用多个测试-o,并将它们括在括号中(感谢希安指出这一点):

find /lmms/samples/ \( -name "warp01*" -o -name "JR_effect2k*" ... \) -exec ...

(引用每个模式以避免 shell 通配问题)。

总而言之,如果您修复名称测试并find

-exec zip ~/Desktop/files.zip {} +

它应该做正确的事。

答案2

您只需用 a或( ) 终止您的-exec选项。您的文件必须位于您放入存档 IIRC 中的文件之前,因此这将变为:;+man findzip

find ... -exec zip ~/Desktop/files.zip {} ;
find ... -exec zip ~/Desktop/files.zip {} +

+版本在命令末尾聚合参数,并为所有文件zip调用一个参数(如果命令真的很长,则调用多个参数)。它的 I/O 密集程度较低,但缺点是您只能在最后使用一次,就在.该版本更灵活,但需要每个文件。zipzip{}+;zip

没有找到替代解决方案

您的谓词也有问题-name,@StephenKitt 为您提供了正确的语法。

这是另一种语法,它使用zip的能力来理解 globbing 模式,例如file*.因此它不使用find,更接近您最初的建议,并且对于不习惯的人来说可能不太容易出错find

$ zip -r  ~/Desktop/files.zip /lmms/samples/ --include 'warp01*' 'JR_effect2k*' 'clean_low_key*' 'q_kick_2*' 'sticky_q_kick*' 'upright_bass*' 'pizzi*' 'chorded_perc*' 'Tr77_kick*' 'Tr77_tom1*' 'Tr77_cym*' 'hihat_008a*' 'Hat_o.ds' 'Hat_c.ds' 'Kickhard.ds' 'Tr77_snare*'

注意:模式之间用空格分隔。它们周围的引号是强制性的,否则这些模式可能由您的 shell 解释,而不是由zip.

答案3

出于性能和“空白”原因,我强烈建议使用-print0 | xargs -r0,例如

find /foo/bar -xdev -type f -mtime -2 -print0 | xargs -r0 zip "$HOME/foo-bar.zip"

在你的情况下它应该看起来像

find /lmms/samples/ -name warp01*,JR_effect2k*,clean_low_key*,q_kick_2*,sticky_q_kick*,upright_bass*,pizzi*,chorded_perc*,Tr77_kick*,Tr77_tom1*,Tr77_cym*,hihat_008a*,Hat_o.ds,Hat_c.ds,Kickhard.ds,Tr77_snare* -print0 | xargs -r0 zip ~/Desktop/files.zip

相关内容