Nehmen wir an, ich habe einen Ordner mit Hunderten oder Tausenden von Dateien, die alle nach dem folgenden Schema benannt sind:
<random number of variable length>_<date code in YYYYMMDD format>.jpg
Beispiel:
73923_20180927.jpg
4457582_20180927.jpg
...
18733557_20190401.jpg
23573_20190401.jpg
...
Ich erwarte von meinem Bash-Skript, dass es eine Liste dieser Datumscodes druckt, d. h.
20180927
20190401
...
Das klingt nach einer einfacheren Aufgabe, als es ist. Da das Schema immer dasselbe ist, habe ich es bereits geschafft, eine Zeichenfolgenmanipulation anzuwenden, um nur den erforderlichen Teil der Dateinamen auszudrucken. Ich versuche jedoch immer noch herauszufinden, wie ich jedes Datum nur einmal ausdrucken kann.
Gibt es einen guten Ausweg?
Antwort1
Vorausgesetzt, alle Dateinamen entsprechen dem Muster ./*_*.jpg
:
for name in ./*_*.jpg; do
name=${name##*_} # 4457582_20180927.jpg --> 20180927.jpg
printf '%s\n' "${name%.jpg}" # 20180927.jpg --> 20180927
done | sort -u
Dies durchläuft alle Namen. Für jeden Namen wird dann die längste Präfixzeichenfolge entfernt, die mit übereinstimmt *_
. Anschließend wird die verbleibende Zeichenfolge ohne .jpg
Suffix ausgegeben.
Alle Strings werden dann so sortiert, dass am Ende nur eine Liste eindeutiger Strings ausgegeben wird.
Wenn das Risiko besteht, dass das Verzeichnis leer sein könnte, sollten Sie nullglob
vor der Schleife die Shell-Option ( shopt -s nullglob
) setzen. Dadurch wird die Schleife gar nicht ausgeführt, anstatt einmal mit dem nicht erweiterten Globbing-Muster in $name
.
Ohne besonderen Grund können Sie es wie folgt ohne machen sort
:
declare -A skip=()
for name in ./*_*.jpg; do
key=${name##*_} # 4457582_20180927.jpg --> 20180927.jpg
key=${key%.jpg} # 20180927.jpg --> 20180927
if [[ ! -v skip[$key] ]]; then
printf '%s\n' "$key"
skip[$key]=1
fi
done
Hier verfolge ich, welche Strings bereits als Schlüssel in einem assoziativen Array ausgegeben wurden. skip
Ein String wird nicht ausgegeben, wenn er einem Schlüssel im Array entspricht.
Antwort2
Vorausgesetzt, es gibt wirklich keine unzulässigen Dateinamen, führen Sie in diesem Verzeichnis Folgendes aus:
ls -U | awk '-F[_.]' '{ print $2 }' | sort | uniq