Mein Problem: Die vom Find-Befehl zurückgegebenen Ergebnisse scheinen nicht „aktuell“ zu sein.
Ich habe ein Bash-Skript, in dem:
- ich bekomme die Liste der GIF-Dateien in einem Verzeichnis
- ich verwende convert (von imagemagick) auf ihnen, um png zu machen
- ich erhalte die Liste der PNG-Dateien im selben Verzeichnis (die möglicherweise die zuvor generierten Dateien enthält, wenn sich hier GIF-Dateien befanden)
- ich optimiere sie mit optipng
Wenn ich dieses Skript so lasse, wie es ist, wird das entsprechende PNG nicht gefunden, wenn ich ein GIF habe. Wenn ich das Skript mit einem Lesen von der Tastatur zum Anhalten zwinge, wird das neue PNG gefunden.
Meine Interpretation:
- Entweder kehrt die Konvertierung sofort zurück, sodass die PNG-Suche ausgeführt wird, bevor die GIF-zu-PNG-Datei erstellt wird. Wie kann man in diesem Fall den nächsten Befehl zwingen, darauf zu warten?
- oder der Find-Befehl verwendet einige Systemfunktionen, deren Aktualisierung Zeit benötigt. Wie kann man in diesem Fall eine Aktualisierung von Dirinfo erzwingen?
Danke
Antwort1
Befolgen Sie Ihre vier Schritte (ignorieren Sie die Schritte zum Abrufen der Liste, da diese nicht erforderlich sind):
#!/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 {} \;
Dadurch werden zunächst alle regulären Dateien gefunden, deren Namen auf .gif
oder unter enden $topdir
, und diese werden in PNG-Bilder umgewandelt.
Anschließend findet es alle PNG-Bilder auf die gleiche Weise und führt sie optipng
auf jedem aus (beachten Sie, dass ich nichts über diesen Befehl weiß, also kann ich hier nur raten). Der zweite Befehl find
würde auch PNG-Bilder finden, die möglicherweise vor der Ausführung des Skripts vorhanden waren.
optipng
Wenn Sie nur die neu erstellten PNG-Bilder ausführen möchten , verwenden Sie ein einzelnes find
:
find "$topdir" -type f -name '*.gif' -exec sh -c '
for gifpath do
pngpath=${gifpath%.gif}.png
convert "$gifpath" "$pngpath"
optipng "$pngpath"
done' sh {} +
Verwandt:Die Option -exec von „find“ verstehen
Oder verwenden **
Sie „in “, bash
um rekursiv unter folgendem abzugleichen $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
In jedem einzelnen Codeteil oben optipng
wurde der Befehl erst ausgeführt, wenn er convert
beendet war. Wenn dies immer noch zu Problemen der gleichen Art führt, wie Sie sie beschreiben (die PNG-Bilder sind nach nicht verfügbar convert
), würde ich nach Fehlermeldungen suchen, die beschreiben, was schiefgelaufen ist.
Antwort2
Jemand hat einen Synchronisierungsbefehl empfohlen, der das System dazu veranlasst hätte, sämtliche Caches zu leeren und so unerledigte Festplattenvorgänge zu vermeiden.
Aber dieser seltsame Fehler ist verschwunden. Meine Vermutung: Syntax-Eigenart meinerseits, nicht erkannt. Trotzdem danke für Ihre Hilfe, und so sieht es jetzt aus:
#!/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