我试图在每个不包含任何子目录的目录中放置一个包含目录内容的 zip 文件。
如果目录名和/或文件名中没有空格,则以下命令有效,但如果有空格则失败:
find pictures/ -type d -links 2 -execdir sh -c "pwd; echo '{}'; zip -v '{}/{}.zip' '{}/*' -x \*.zip -x \*.id" \;
我不明白为什么它会失败,因为我像往常一样引用了“{}”。还尝试了“{}”。换句话说,它应该使用 A/B/C/* 的内容创建 A/B/C/C.zip。如果“C”中有空格,我得到:
zip warning: name not matched: ./C/*
zip error: Nothing to do! (./C/./C.zip)
答案1
对于您的 版本find
,{}
字符串中的 会被文件名替换。用作字符串的一部分几乎总是错误的{}
,因为文件名就是这样插入的。这里,文件名用作 shell 脚本片段。如果有一个名为的目录a'$(touch wibble)'
,那么您的命令将执行 shell 代码
pwd; echo 'a'$(touch wibble)''; zip -v 'a'$(touch wibble)'/a'$(touch wibble)'.zip' 'a'$(touch wibble)'/*' -x \*.zip -x \*.id"`
请注意它如何执行命令touch wibble
(四次)。
您需要将文件名作为参数传递给 shell 代码片段。这是可靠地使用find -exec
或find -execdir
调用 shell 的唯一方法(除非文件名被限制为没有特殊字符,包括空格)。之后的第一个参数sh -c SCRIPT
可以从脚本中访问为"$0"
。
此外,zip
要压缩的文件列表中不接受通配符,因此通配符必须不加引号,以便由 shell 扩展。
find pictures/ -type d -links 2 -execdir sh -c 'pwd; echo "$0"; zip -v "$0/$0.zip" "$0/"* -x \*.zip -x \*.id' {} \;
答案2
像这样改变它:
find pictures -type d -links 2 -execdir \
sh -c 'pwd; echo "$1"; zip -vr "$1/$1.zip" "$1" -x \*.zip -x \*.id' sh {} \;