我的问题: find 命令返回的结果似乎不是“最新的”。
我有一个 bash 脚本,其中:
- 我得到目录中的 gif 文件列表
- 我在它们上使用convert(来自imagemagick)来制作png
- 我获得了同一目录中的 png 文件列表(如果这里有 gif 文件,则可能包含先前生成的文件)
- 我用 optipng 优化它们
如果我按原样保留此脚本,当我有 gif 时,找不到相应的 png。如果我通过键盘读取强制脚本暂停,则会找到新的 png。
我的解释:
- 要么转换立即返回,所以 find png 在创建 gif 到 png 文件之前执行。在这种情况下,如何强制等待下一个命令呢?
- 或者find命令使用了一些需要时间更新的系统功能。在这种情况下,如何强制更新目录信息?
谢谢
答案1
按照您的四个步骤(忽略“获取列表...”步骤,因为不需要它们):
#!/bin/bash
topdir=some/directory/path
find "$topdir" -type f -name '*.gif' -exec sh -c '
for gifpath do
convert "$gifpath" "${gifpath%.gif}.png"
done' sh {} +
find "$topdir" -type f -name '*.png' -exec optipng {} \;
这将首先找到名称以.gif
in 或 under结尾的所有常规文件$topdir
,并将它们转换为 PNG 图像。
然后它以相同的方式找到所有 PNG 图像并optipng
在每个图像上运行(请注意,我对这个命令一无所知,所以我只是在这里猜测)。第二个find
也会找到运行脚本之前可能存在的 PNG 图像。
如果您只想optipng
在新创建的 PNG 图像上运行,请使用单个find
:
find "$topdir" -type f -name '*.gif' -exec sh -c '
for gifpath do
pngpath=${gifpath%.gif}.png
convert "$gifpath" "$pngpath"
optipng "$pngpath"
done' sh {} +
或者,使用**
inbash
在 下递归匹配$topdir
:
#!/bin/bash
topdir=some/directory/path
shopt -s globstar nullglob dotglob
for gifpath in "$topdir"/**/*.gif; do
if [ -f "$gifpath" ]; then
pngpath=${gifpath%.gif}.png
convert "$gifpath" "$pngpath"
optipng "$pngpath"
fi
done
在上面的每一段代码中,optipng
命令在命令完成之前不会运行convert
。如果这仍然给您带来与您所描述的性质相同的问题(PNG 图像在 后不可用convert
),那么我会查找描述问题所在的错误消息。
答案2
有人推荐了一个sync命令,这会让系统刷新所有缓存,然后避免未完成的磁盘业务。
但这个奇怪的bug却消失了。我的猜测:我的语法怪癖,没有检测到。尽管如此,还是感谢您的帮助,现在的情况如下:
#!/bin/bash
clear
mapfile -t tab < <(jq -r '.[] | .' img_folders_to_optimize.json)
printf '%s\n' "${tab[@]}" | while read -r folder; do
echo "dossier à traiter : $folder"
cd "$folder" || exit
# GIF
for filepath in *.gif; do
echo "GIF : $filepath"
nb_frames=$(identify -format %n "$filepath")
if [ "$nb_frames" != 1 ]; then
echo "animated"
else
echo "convert to png"
filepath_png=${filepath/\.gif/.png}
convert "$filepath" "$filepath_png" &>/dev/null
echo "converted"
fi
done
# PNG
for filepath in *.png; do
echo "PNG : $filepath"
echo "optimize"
optipng -o7 -strip all "$filepath" &>/dev/null
echo "convert lossless to webp"
filepath_webp=${filepath/\.png/.webp}
cwebp -lossless "$filepath" -o "$filepath_webp" &>/dev/null
done
# JPG
for filepath in *.jpg; do
echo "JPG : $filepath"
echo "optimize"
mogrify -quality 70 "$filepath"
echo "convert lossy to webp"
filepath_webp=${filepath/\.jpg/.webp}
cwebp -q 50 -m 4 -mt "$filepath" -o "$filepath_webp"
done
echo "dossier traité"
done