我已经尝试运行这个脚本几次了,但它一直挂着。我有 60,000 张图像,它经过大约 1000 张后就停止了。我一直在运行 top 命令,进程 pngquant 似乎消失了。任何帮助将非常感激。
我得到的最后一个输出是
Optimized PNG: ./12/thumbnail/112.png
Optimized PNG: ./12/thumbnail/photography.png
Optimized PNG: ./12/thumbnail/Christmas-01.png
Optimized PNG: ./12/thumbnail/OA1920.png
error: cannot open ./12/thumbnail/The for reading
Optimized PNG: ./12/thumbnail/The
error: cannot open Official for reading
Optimized PNG: Official
error: cannot open AndreasCY for reading
Optimized PNG: AndreasCY
然后它就停了。脚本看起来像这样。
#!/bin/bash
cd /var/www/html/wp-content/uploads/2014/
for PNG in $(find . -name '*.png'); do
pngquant --ext .png --force 256 ${PNG}
echo "Optimized PNG: ${PNG}"
done
答案1
瑞的回答包含了一些很好的建议,尽管他似乎错过了你的命令失败的真正原因。从输出中可以看出,您有一个名为../12/thumbnail/The Official AndreasCY ….png
当你说
for PNG in $(find . -name '*.png')
这就像说
适用于 ./12/thumbnail/112.png ./12/thumbnail/photography.png ./12/thumbnail/Christmas-01.png \ ./12/thumbnail/OA1920.png ./12/thumbnail/官方 AndreasCY …。.png...
结果./12/thumbnail/The
,Official
、 、 和AndreasCY
被视为单独的文件名,而且,由于它们不是单独的文件名,因此您会得到错误。您应该非常小心地使用它$(…)
来生成文件名列表 - 我的意思是,如果可能的话,请避免这样做。
find … -exec
是一个更好的方法。然而,Rui 给出的命令不起作用:-exec "Optimized PNG: "
会失败,因为没有这样的命令"Optimized PNG: "
。
我建议你保留你原来的答案和Rui的答案的以下部分:
#!/bin/sh cd /var/www/html/wp-content/uploads/2014 (你实际上并不需要末尾的“/”。) 寻找 。 -name '*.png' -type f ...
然后使用以下操作之一完成它:
-exec pngquant --ext .png --force 256 {} \; -exec echo "Optimized PNG:" {} \;
-exec pngquant --ext .png --force 256 {} \; -printf "Optimized PNG: %p\n"
-exec sh -c 'pngquant --ext .png --force 256 "$1"; echo "Optimized PNG: $1"' sh {} \;
, 或者-exec myscript {} \;
哪里myscript
#!/bin/sh pngquant --ext .png --force 256 "$1" echo "Optimized PNG: $1"
请注意,您应该始终引用 shell 变量(例如"$PNG"
和"$1"
),除非您有充分的理由不这样做,并且您当然你知道你在做什么。相比之下,虽然大括号(例如,${PNG}
)可能很重要,但它们不如引号重要。而且,根据一般原则,我建议您使用,#!/bin/sh
除非您明确编写依赖于 bash 功能的脚本,并且无法与 POSIX 兼容的 shell 一起使用 — 我建议不要这样做。
答案2
在您的脚本中,查找输出被扩展为实际的命令行,该命令行在大小上有限制。因此,当 find 提供的参数超过大小时,其余的将被忽略。
这篇文章涉及有问题的: http://www.cyberciti.biz/faq/argument-list-too-long-error-solution/
find 命令也是一个非常强大的命令,并且有一个调用命令的选项,这是处理大文件时摆脱这些限制的方法之一。
您可以像这样执行命令:
find $DIR -name '*.png' -type f -exec command {} \;
其中 {} 是正在处理的文件,类型 f 是定义您正在处理的文件,$DIR 是命令递归工作的基目录。
在一条生产线中完成您想要的操作的一种简单方法是:
find /var/www/html/wp-content/uploads/2014 . -name '*.png' -type f \
-exec pngquant --ext .png --force 256 {} \; -exec echo "Optimized PNG: " {} \;
(\ 用于将命令分成两行以增加帖子的清晰度)
我还将在这里留下一篇关于将 find 与 exec 选项一起使用的文章。
http://linuxaria.com/howto/linux-shell-how-to-use-the-exec-option-in-find-with-examples
答案3
Globbing 语法可以直接放入 for 循环中。你find
根本不需要。如果您直接在 for 循环中使用通配符,则不必担心分词,因为 shell 会自动处理这个问题。
当 shell 变量出现在命令中时,引用它们也是一个好主意,否则它们在替换后将进行分词。
最后,更喜欢printf
而不是echo
,因为如果您的文件名中包含某些字符,它的行为会更正确,并且在不同的实现之间更可移植。
for PNG in *.png; do
pngquant --ext .png --force 256 "$PNG"
printf "Optimized PNG: %s\n" "$PNG"
done
在 zsh 和 bash 中以及相关选项集,你可以像这样进行递归 glob:
for PNG in **/*.png; do
pngquant --ext .png --force 256 "$PNG"
printf "Optimized PNG: %s\n" "$PNG"
done
这将导致搜索下降到子目录,就像find
命令一样。但是,这不是 POSIX 标准,因此如果您需要在所有类似 POSIX 的系统上可移植地工作,您应该使用其他答案之一。