Bash extrahiert erste Zahl aus dem Dateinamen

Bash extrahiert erste Zahl aus dem Dateinamen

Ich versuche, Dateien wie folgt zu verschieben:

...
DLG023-00-01-sprite.TextGrid.json
DLG023-00-01.prosody.json
DLG023-01-01-sprite.ogg
DLG023-00-02-sprite.TextGrid.json
DLG023-00-02.prosody.json
DLG023-01-02-sprite.ogg
...
DLG028-00-01-sprite.TextGrid.json
DLG028-00-01.prosody.json
DLG028-01-01-sprite.ogg
...

in die jeweiligen Ordner, z. B.: Verschieben Sie die Datei dorthin, dialogue023/wenn sie mit beginnt DLG023; dorthin, dialogue024/wenn sie mit beginnt DLG024; und so weiter.

Alle Dateien und Verzeichnisse befinden sich auf derselben Ebene.

Mit anderen Worten versuche ich, Befehle wie diesen zu erzeugen:

mv DLG023-00-01-sprite.ogg dialogue023/

Wie kann ich die erste Zahl aus dem Dateinamen extrahieren?

Bisher habe ich Folgendes:

for i in DLG*-*-*-sprite.ogg; do echo "${i//[^0-9]}";done

Dies gibt jedoch alle Ziffern aus (z. B. 230001), obwohl ich nur die erste Ziffer möchte (z. B. 23).

Antwort1

Ich gehe davon aus, dass Sie OS X verwenden, wo diese -tOption nicht verfügbar ist mv. Dies wird quälend langsam sein, wenn das Skript Tausende von Dateien verarbeitet.

    for file in DLG*; do
    # Extract the three digits after DLG
    getnum=${file%%-*}
    getnum=${getnum#???}

    # make the directory dialogue### or exit if there is an error
    echo mkdir -p "dialogue${getnum}" || exit

    echo mv "$file" "dialogue${getnum}"
    done

Entfernen Sie das „ echoVorher“ mkdirund mv„Wenn die Ausgabe zufriedenstellend ist“.

Antwort2

Sie können den mv-Befehl folgendermaßen generieren:

for f in DLG*; do echo "$f" | sed 's/DLG\([0-9]\+\).*/mv "\0" "dialogue\1\/"/g'; done

Jetzt werden die Befehle folgendermaßen ausgedruckt:

mv "DLG023-00-01.prosody.json" "dialogue023/"
[...]
mv "DLG028-00-01.prosody.json" "dialogue028/"
[...]

Wenn es das ist, was Sie möchten, leiten Sie die Ausgabe einfach weiter an bash:

for f in DLG*; do echo "$f" | sed 's/DLG\([0-9]\+\).*/mv "\0" "dialogue\1\/"/g'; done | bash

Antwort3

Einzeilige Lösung mit find:

find . -name DLG* -exec bash -c 'DEST=$(echo "$0" | sed -r "s/DLG([0-9]+)-.*/dialogue\1/"); mkdir "$DEST"; mv "$0" "$DEST"' {} \;
  • findDer Befehl sucht nach DLG*Dateien aus diesem Verzeichnis.
  • Führen Sie für jedes Ergebnis den bash -cSatz aus.

In dem bashSatz:

  • DEST=$(echo "$0" | sed -r "s/DLG([0-9]+)-.*/dialogue\1/");wählt jedes Ergebnis aus find ( $0) aus, sedersetzt alle Zahlen vor der ersten -(DLG([0-9]+)-.*) durch dialoguedie folgenden Zahlen ( dialogue\1) und setzt sie in eine Variable namens ein DEST.
  • mkdir "$DEST"erstellt den erforderlichen Ordner.
  • mv "$0" "$DEST"'verschiebt die Datei in dieses Verzeichnis.

Antwort4

Ein paar Ideen:

for i in DLG*-\*-\*-sprite.ogg; do echo "${i//[^0-9]}" | head -c 2; echo ;done

Wenn Sie sicher sind, dass sie alle gleich lang sind:

for i in DLG*-\*-\*-sprite.ogg; do echo "${i:3:3}" ;done

verwandte Informationen