
Meu problema: os resultados retornados pelo comando find não parecem "atualizados".
Eu tenho um script bash no qual:
- eu recebo a lista de arquivos gif em um diretório
- eu uso convert (do imagemagick) neles para fazer png
- recebo a lista de arquivos png no mesmo diretório (que pode conter os gerados anteriormente se houvesse arquivos gif aqui)
- eu os otimizo com optpng
Se eu deixar esse script como está, quando tiver um gif, o png correspondente não será encontrado. Se eu forçar a pausa do script com uma leitura do teclado, o novo png será encontrado.
Minha interpretação:
- ou a conversão retorna imediatamente, então find png é executado antes que o arquivo gif para png seja criado. Nesse caso, como forçar o próximo comando a esperar por ele?
- ou o comando find usa algumas funções do sistema que precisam de tempo para serem atualizadas. Neste caso, como forçar a atualização em dir info ?
Obrigado
Responder1
Seguindo suas quatro etapas (ignorando as etapas "obter a lista...", pois elas não são necessárias):
#!/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 {} \;
Isso primeiro encontraria todos os arquivos regulares cujos nomes terminam em .gif
ou abaixo $topdir
e os converteria em imagens PNG.
Em seguida, ele encontra todas as imagens PNG da mesma maneira e executa optipng
cada uma delas (observe que não sei nada sobre esse comando, então estou apenas supondo aqui). O segundo find
também encontraria imagens PNG que possivelmente existiam antes da execução do script.
Se você deseja executar apenas optipng
as imagens PNG recém-criadas, use um único find
:
find "$topdir" -type f -name '*.gif' -exec sh -c '
for gifpath do
pngpath=${gifpath%.gif}.png
convert "$gifpath" "$pngpath"
optipng "$pngpath"
done' sh {} +
Relacionado:Compreendendo a opção -exec de `find`
Ou, usando **
in bash
para corresponder recursivamente em $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
Em cada trecho de código acima, o optipng
comando não seria executado até que o convert
comando fosse concluído. Se ainda assim isso causar problemas da mesma natureza que você descreveu (as imagens PNG não estão disponíveis depois convert
), procurarei mensagens de erro que descrevam o que deu errado.
Responder2
Alguém recomendou um comando de sincronização, que faria com que o sistema liberasse todos os caches e evitasse negócios de disco inacabados.
Mas esse bug estranho desapareceu. Meu palpite: peculiaridade de sintaxe da minha parte, não detectada. No entanto, obrigado pela sua ajuda, e aqui está o que parece agora:
#!/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