![Найти результат неактуально](https://rvso.com/image/164630/%D0%9D%D0%B0%D0%B9%D1%82%D0%B8%20%D1%80%D0%B5%D0%B7%D1%83%D0%BB%D1%8C%D1%82%D0%B0%D1%82%20%D0%BD%D0%B5%D0%B0%D0%BA%D1%82%D1%83%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE.png)
Моя проблема: результаты, возвращаемые командой find, кажутся «неактуальными».
У меня есть bash-скрипт, в котором:
- я получаю список gif-файлов в каталоге
- я использую convert (из imagemagick) для создания png
- я получаю список файлов png в том же каталоге (который может содержать ранее сгенерированные файлы, если здесь были файлы gif)
- я оптимизирую их с помощью optipng
Если я оставлю этот скрипт как есть, когда у меня есть gif, соответствующий png не будет найден. Если я заставлю скрипт остановиться с помощью чтения с клавиатуры, то будет найден новый png.
Моя интерпретация:
- либо convert немедленно возвращается, поэтому find png выполняется до создания файла gif to png. В этом случае, как заставить следующую команду ждать его?
- или команда find использует некоторые системные функции, которым нужно время для обновления. В этом случае, как принудительно обновить dir info?
Спасибо
решение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
или ниже $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 {} +
Связанный:Понимание опции -exec команды `find`
Или, используя **
in bash
для рекурсивного сопоставления с $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
Кто-то порекомендовал команду синхронизации, которая заставила бы систему очистить все кэши и избежать незавершенных операций с диском.
Но этот странный баг исчез. Мое предположение: синтаксическая причуда с моей стороны, не обнаружена. Тем не менее, спасибо за помощь, и вот как это выглядит сейчас:
#!/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