我的問題: 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