Gemeinsamkeiten/Muster in einer Reihe von Dateien finden

Gemeinsamkeiten/Muster in einer Reihe von Dateien finden

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 .jpgSuffix 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 nullglobvor 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. skipEin 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

verwandte Informationen