bash extrahiere die erste Zahl aus dem Dateinamen

2

Ich versuche Dateien so 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
...

z. B. verschieben Sie die Datei nach dialogue023/ wenn es anfängt mit DLG023; zu dialogue024/ wenn es anfängt mit DLG024; und so weiter.

Alle Dateien und Verzeichnisse befinden sich auf derselben Ebene.

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

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

Wie kann ich die erste Zahl aus dem Dateinamen extrahieren?

Bisher habe ich das bekommen:

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

Dies gibt jedoch alle Ziffern aus (z. B. 230001), wenn nur die erste (z. B. 23) gewünscht wird.

Fabien Snauwaert
quelle
1
Das tut es eigentlich nicht Extrakt die Zahlen, also keine Antwort auf die Frage, aber grundsätzlich kann man auch so etwas machen for num in $(seq -f '%03g' 1 999); do test -d dialogue${num}||mkdir dialogue${num}; mv -t dialogue${num} DLG${num}-*; done gefolgt von rmdir dialogue* -- das -f '%03g' Das bedeutet, dass alle Zahlen mindestens dreistellig mit Nullen aufgefüllt sind. Da 999 dreistellig passt, werden alle Zahlen in den Verzeichnisnamen dreistellig. Einfach rmdir Wenn das Verzeichnis nicht leer ist, schlägt dies fehl. Klammer für unwichtige Fehlerausgabe von mv über nicht vorhandene Dateien.
a CVn
Ist es immer Zeichen 4-6?
Paul
Danke, Michael, das ist der clevere Weg, das zu erreichen.
Fabien Snauwaert
Es sind immer die Zeichen 3-6 (oder 4-6 im Moment.)
Fabien Snauwaert

Antworten:

1

Ich gehe davon aus, dass Sie OS X verwenden, welches das nicht hat -t Option in mv. Dies wird schmerzhaft langsam, 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

Entferne das echo Vor mkdir und mv wenn die Ausgabe zufriedenstellend ist.

fd0
quelle
Klappt wunderbar. Es passiert nicht im Handumdrehen, aber bei 19 Ordnern in Sekunden. Aus reiner Neugier: Gibt es eine Möglichkeit, die drei Ziffern in nur einem Schritt zu extrahieren?
Fabien Snauwaert
@Fabien Snauwaert- Sie können die Erweiterung der Teilzeichenfolge in einem Schritt anstelle der Entfernung der Teilfolge verwenden. Die Erweiterung der Teilzeichenfolge ist jedoch nicht in jeder Shell verfügbar.
fd0
0

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

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

Nun werden die Befehle folgendermaßen gedruckt:

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

Wenn es das ist, was Sie wollen, leiten Sie diese Ausgabe einfach weiter bash und es wird ausgeführt:

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

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"' {} \;
  • find Befehl suchen DLG* Dateien aus diesem Verzeichnis.
  • Für jedes Ergebnis führen Sie die bash -c Satz.

In dem bash Satz:

  • DEST=$(echo "$0" | sed -r "s/DLG([0-9]+)-.*/dialogue\1/"); wählt jedes Ergebnis von find ( $0 ) und verwenden sed Ersetzen Sie alle Zahlen vor der ersten - (DLG ([0-9] +) -. *) Mit dialogue mit diesen Nummern folgen ( dialogue\1 ) und in eine Variable namens DEST.
  • mkdir "$DEST" erstellt den gewünschten Ordner.
  • mv "$0" "$DEST"' verschiebt die Datei in dieses Verzeichnis.
jherran
quelle
1
Während dies die Frage beantworten kann, wäre es eine bessere Antwort, wenn Sie eine Erklärung geben könnten Warum es tut so
DavidPostill
0

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
fede.evol
quelle