Dateiennummerierung erniedrigen mittels Terminal

L

Lorzel

Aktives Mitglied
Thread Starter
Dabei seit
01.06.2021
Beiträge
538
Reaktionspunkte
69
Hallo!
Ich möchte folgendes Problem (am liebsten mit dem Terminal) lösen:
Ich habe Dateien mit folgenden Namen

Name01AufgabeA
Name01AufgabeB

Name02AufgabeA

Name03AufgabeA
Name03AufgabeB
Name03AufgabeC

Name05AufgabeA
Name05AufgabeB
Name05AufgabeC

Name06AufgabeA
Name06AufgabeB

Name07AufgabeA

Name08AufgabeA
Name08AufgabeB
...
Und ich möchte die Lücke zwischen 03 und 05 schließen. Dh alle Nummern größergleich 05 müssen um eins erniedrigt werden.
(wären es nur ein paar Dateien würde ich es natürlich von Hand machen. Es handelt sich jedoch eine Datenbank, wo dutzende Dateien sind)

Ich fände es nun ganz super, wenn man das mit einem Terminalbefehl machen könnte.
Also wahrscheinlich so was, wie
for j from 5 to 9 do replace "0j" to "0j-1"...
for j from 10 to .... do replace "j" to "j-1"...
aber mir fehlen die Syntax-Kenntnisse... und vielleicht kann man auch das Problem der Ein- und Zweistelligkeit verbinden (bei meiner Stokelvariante würde "10" zu "9" anstatt "09".

Hat hier jemand Expertise😃?
 
new_index=3; last_index=""; for file in Name*Aufgabe*; do number=$(echo $file | grep -o '[[:digit:]]*'); if (( $number >= 5 )); then if [ "$last_index" != "$number" ]; then last_index=$number; new_index=$((new_index+1)); fi; new_file=$(echo $file|sed -E 's/[0-9]+/'$(printf "%02d" $new_index)'/g'); echo "mv $file $new_file"; fi; done

* das ist für bash
* new_index=3 fängt dann bei 4 an neu zu nummerieren
* es geht davon aus dass die file Namen wirklich "Name*Aufgabe*" sind
* ja, das geht sicher besser, hab ich halt so hingetippt, sorry ;)
* das macht erstmal nur echos der mv Kommandos
 
  • Gefällt mir
Reaktionen: Lorzel, win2mac, tigion und 2 andere
@oglimmer Danke schon mal!
...Ja also das "Name" würde ich dann ersetzen durch das tatsächliche Kürzelkauderwelsch. Das "Aufgabe" ist in Wirklichkeit leider nicht das gleiche.
Falls es wen interessiert/es da klarer macht: Der Teil "Name" ist in jedem Dateinamen gleich (Themengebiet, Schwierigkeitsstufe). Nach der Unterthemennummer kommt ein für "Aufgabe" ein Stichwort zur Aufgabe. Dieses Stichwort ist für jede Aufgabe verschieden...

Wenn ich es richtig verstehe, dann definierst Du zunächst zwei Parameter. Dann soll "number" definiert werden, indem die "digit" aus dem Dateinamen benutzt wird. Da soll eine Aktion erfolgen, falls die Bedingung >= 5 erfüllt ist und wenn dann noch last_index gleich der number ist, dann soll der "neue Index" (der ja am Anfang 3 war) um 1 erhöht werden. mit sed ersetzt Du wahrscheinlich die Nummern und dann sollen sie noch geschrieben werden. ..so grob.

Lässt sich da dann noch irgendwie einbauen, dass alles hinter der zweistelligen Zahl erhalten bleibt?
Und - ich weiß, ne ganz basige Frage - kann ich noch einbauen, dass obiges nur auf ein bestimmtes Verzeichnis (Vorlage zum Reinkopieren des Pfades) angewandt wird? (ist mir sonst zu heikel).
 
du kannst das einfach mal ausprobieren, weil ja nichts wirklich umbenannt wird, sondern es wird nur der "mv" befehl ausgegeben. Das sieht man bei echo "mv $file $new_file", d.h. da wird nicht mv gemacht, sondern echo "mv".

Das hinter der Number wird beibehalten:

new_file=$(echo $file | sed -E 's/[0-9]+/'$(printf "%02d" $new_index)'/g')

der neue filename ist der alt filename, nur dort wo die zahlen stehen wird, der neue index eingesetzt.
* echo schreibt den alten filenamen und piped es durch das sed kommando
* sed ist ein stream editor, d.h. man kann den zeichenstrom der vom echo kommt, dann bearbeiten
* das -E im sed bedeutet dass man "extended regular expressions" verwenden will
* dann kommt die regular expression als search and replace
* dann sucht er [0-9]+ also mind. 1 oder viele Zahlen
* und ersetzt diese durch das ergebnis der sub-shell von "printf"
* das printf braucht man damit man die fuehrenden nullen hat
 
  • Gefällt mir
Reaktionen: KOJOTE, Difool und ruerueka
OK, ich habs jetzt endlich getestet. (Hatte mich ne zeitlang gesträubt, wollte erst ein Szenario basteln, wo auf jeden Fall keine Umbenennungen an unerwünschten Orten passieren würden.)
Mein Bericht dazu:
Name*Aufgabe*
passt noch nicht so richtig. Hab's eventuell auch nicht richtig erklärt, hier nun besser:
Der Dateinamensteil "Name" ist tatsächlich für alle Datei konstant. Der Namensteil "Aufgabe" ist jedoch nicht konstant - dies hatte ich versucht mit "AufgabeA" vs "AufgabeB" usw. deutlich zu machen.
Konkret: Bei "Name" steht immer "KSAufgabePHSW", dies ist die Kategorie der Dateien. Dann folgt die Nummer, etwa "05" und danach kommt der Name der (Unter-)Aufgabe, zB "Federpendel" oder "SignalOszi".
Bedeutet zB, der Dateiname "KSAufgabePHSW06WellenDef" soll werden zu "KSAufgabePHSW05WellenDef" und "KSAufgabePHSW07FortschrWellen" soll werden zu "KSAufgabePHSW06FortschrWellen".
Dh, ich kann mit einem konstanten Ausdruck a la "Aufgabe" nicht alle Dateinamen erfassen.

Ich habe nun "Aufgabe" ersetzt durch konkrete Unteraufgabennamen (etwa "WellenDef" oder "FortschrWellen"), um zu testen, ob Deine Kommandos (#2) damit funktionieren. Sie tun's! Allerdings wird die Nummer nicht um 1 erniedrigt, sondern die Nummer wird für ALLE auf 04 gesetzt.

Kann jemand bei diesen beiden Sachen nachbessern? Oder mir eventuellen Bedienungsfehler erklären?
 
Zuletzt bearbeitet:
mmmh, muss man nicht nur

Diff:
for file in Name*Aufgabe*

durch

Diff:
for file in KSAufgabePHSW*

ersetzen?

Ich habe das mal in ein GitHub repo gepackt: https://github.com/oglimmer/dateiennummerierung-erniedrigen-mittels-terminal
Ja, es funzt! Also fast - eine Kleinigkeit passt nicht: die Zähler werden nun gleich um 2 statt nur um 1verringert.
Danke auch für reinschreiben in GitHub!

Edit: Ah, ich konnte das beheben, habe "new_index=4" gesetzt (statt "new_index=3").
 
Allerdings wird die Nummer nicht um 1 erniedrigt, sondern die Nummer wird für ALLE auf 04 gesetzt.

Kann jemand bei diesen beiden Sachen nachbessern? Oder mir eventuellen Bedienungsfehler erklären?
Dieses ALLE auf 04 passiert nur, wenn ich das Kommando für jeden Dateinamen sukzessive einzeln benutze. ...falls unklar -> kürzer: Hat sich erledigt mit dem Fehler.
 
Auch wenn du es schon geschafft hast.
Ich würde das mit einem Rename-tool machen.

allerdings kommt es darauf an, wie viele nummern das insgesamt sind, da man das für jede zahl exakt einmal machen muss.
Im beispiel geht es ja nur bis 10.

Better Rename könnte z.b. die 5. und 6. Stelle austauschen.

Ich würde ich immer empfehlen ein definiertes Trennzeichen (z.b. _ oder -) zwischen die einzelnen Namensteile zu setzen.
 
Kann mir jetzt noch jemand sagen, wie nun das Kommando die Umbenennung auch tatsächlich ausführen lässt? Also bisher wird das ja nur "simuliert".
 
Auch wenn du es schon geschafft hast.
Ich würde das mit einem Rename-tool machen.

allerdings kommt es darauf an, wie viele nummern das insgesamt sind, da man das für jede zahl exakt einmal machen muss.
Im beispiel geht es ja nur bis 10.
Also in der Simulation werden auch die Zahlen über 09 umbenannt.
Edit: Äh, nee Blödsinn, Du hast Recht. Es werden nur die alten Namen hingeschrieben, keine neuen generiert.
Aber wahrscheinlich kann ich dann Befehl abändern und ab new_index=10 starten.. wo wären da noch Änderungen nötig? (Hinweis: die höchste Nummer bei meinem Problem ist bekannt)
Auch wenn du es schon geschafft hast.
Ich würde das mit einem Rename-tool machen.
Klar, gibt es gute Tools - mit solchen hab ich früher unter Windows (etwa Flexibel Renamer oder Joe) auch gearbeitet.
Aber ich finde das Arbeiten mit dem Terminal charmant und weiterentwickelnd für mich. Denn ich will "ein Tool für alles" oder sagen wir etwas vorsichtiger "ein Tool für vieles". Und die Renamer-Tools haben zudem Einschränkungen, wenn es zu speziell wird, dann geht es nicht und es geht nur umständlich.

Aber Danke für den Hinweis, ich schaue mir Better Rename mal an.
 
Zuletzt bearbeitet:
Bash:
echo "mv $file $new_file"

zu

Bash:
mv $file $new_file

dann werden die files wirklich umbenannt.

--------------------------------

ich habe auch eine neue version ins git gepusht. Da war ein Fehler drin, wenn die nummer im Dateinamen größer als 7 war. Im git repo habe ich files bis 11 drin.
 
Bash:
echo "mv $file $new_file"

zu

Bash:
mv $file $new_file

dann werden die files wirklich umbenannt.

--------------------------------

ich habe auch eine neue version ins git gepusht. Da war ein Fehler drin, wenn die nummer im Dateinamen größer als 7 war. Im git repo habe ich files bis 11 drin.
Danke, funktioniert!
Kann man denn nun auch auf größere Nummern erweitern (bisher wird noch 11 in 10 geändert, 12 jedoch nicht in 11), notfalls auch mit einem separaten Befehl?

Edit: Ähm.. funktioniert doch für alle Nummern!
Also super vielen Dank! Top!!
 
Zuletzt bearbeitet:
...mit einer Sache will noch nerven - das Problem der Umnummerierung tritt in beide Richtungen auf: manchmal fliegt ein Aufgabenthema raus, manchmal muss eins zwischengeschoben werden. Sprich: kann man obiges auch noch modifizieren, sodass man ab einer bestimmten Nummer etwa die 05, alle Nummer um 1 erhöht? Natürlich könnte ich "new_index+1" in "new_index-1" ändern - aber man muss dann wohl "von hinten" anfangen. Weil erst die 05 in 06 ändern, danach die 06 in 07 usw, würde ja dazu führen, dass ich am alle Nummern auf die höchste gesetzt habe. Oder finden die Umbenennung sowie "gleichzeitig" statt?
 
> ...mit einer Sache will noch nerven

nein, nervt mich nicht ;)

> das Problem der Umnummerierung tritt in beide Richtungen auf: manchmal fliegt ein Aufgabenthema raus,
> manchmal muss eins zwischengeschoben werden.
> Sprich: kann man obiges auch noch modifizieren, sodass man ab einer bestimmten Nummer etwa die 05, alle Nummer um 1 erhöht?
> Natürlich könnte ich "new_index+1" in "new_index-1" ändern - aber man muss dann wohl "von hinten" anfangen.
> Weil erst die 05 in 06 ändern, danach die 06 in 07 usw, würde ja dazu führen, dass ich am alle Nummern auf die höchste gesetzt habe.

Ich beschreibe vielleicht mal kurz wie das überhaupt funktioniert:

* es wird eine Liste alle Dateien die dem Schema KSAufgabePHSW* folgen erstellt. Diese Liste wird dann von oben nach unten abgearbeitet
* in der Variable "file" steht immer der Filename drin, der aus der Liste gerade abgearbeitet wird
* in Zeile 9 wird dann die Zahl die im Filename ist rausgeholt und in "number" gespeichert
* in Zeile 10 wird erstmal geprüft ob diese Zahl überhaupt größer oder gleich 5 ist, weil wir alle Dateien mit 1...4 nicht umbenennen wollen
* Zeile 12 schaut ob die Zahl in "number" ungleich der Nummer ist die von dem File (aus der Anfangsliste) vorher ist
* nur wenn die aktuelle Filename-nummer ungleich der vorhergehenden ist, dann wird der "new index" um eins erhöht
* Zeile 17 erstellt den neuen Dateinamen. Kurzgesagt der neue Name ist der alte nur wird die Zahl durch "new index" ersetzt
* Zeile 18 gibt den "mv" Befehl auf der Console aus

Wie man sieht, ist es ein "hoch-zählen" und kein runter-zählen. Die Regel wie umbenannt wird, ist einfach:

* ab 5, ändere die Zahl im Filenamen in den eines Zähler, wobei der Zähler nur hochgezählt wird, wenn sich die Zahl zwischen dem aktuellen File and dem vorherigen geändert hatte

Mir ist anhand deiner Beschreibung nicht klar wie die Regel der Umbenennung jetzt funktioniert.

> Oder finden die Umbenennung sowie "gleichzeitig" statt?

Nein. Der Interpreter führt immer eine Zeile aus, dann die nächste, etc. "Die Nächste" kann natürlich auch mal zurückspringen, wie im Fall der "for Schleife".
 
Also ich wollte auf folgende "Falle" hinaus.
Es gibt ein Element, das das Merkmal "05" trägt. Wenn wir nun ein Programm auf dieses Element loslassen, was sukzessive erst alle "05" in "06" umbenennt, dann alle "06" in "07" umbenennt, dann alle "07" in "08" umbenennt usw.
Wäre das doch ein Bug? Oder?
Denn das Programm würde endlos weiterlaufen, wenn es mindest ein Element findet, was eine Nummer trägt.
Es sei denn: Das finale Ausführen der Umbenennung erfolgt erst nach Abschluss eines Programmdurchlaufs.

Schlüsse vom "Zahlen-erniedrigen"-Programm kann ich hier nicht ziehen, die Problematik tritt dort nicht auf, wie Du es in der gegenläufigen Laufrichtung von new_index und number beschreibst.
 
Nein, das läuft so nicht ab.

Was er macht ist:

* Erst wird eine Liste alle Dateien erzeugt. Diese Liste wird, während das Programm läuft, nicht mehr neu eingelesen, d.h. Umbenennungen verändern diese Liste nicht mehr
* es wird also die (unveränderliche) Liste alle Dateinamen durchgegangen

Ich würde aber bevor ich solche Massenumbenennungen mache, sicher immer ein Backup von allem anlegen. Beim Skriptschreiben weiß man nie was man nicht kaputt macht ;)
 
OK, ich habe dann Programm gründlich untersucht - ich würde das "experimentellen Informatikunterricht" nennen. Durch Befunde, das Programm verstehen.
Feststellung: ich kann damit alles machen, was ich im Punkto Zählerumbenennung machen möchte. Vielen Dank!!! @oglimmer 👍

Meine Anleitung:

$number >= 5 gibt an, welche Zahlen von der Umbenennung betroffen sind.

Verschiedenes Verhalten nach Ausgangslage:
Fall A: Es gibt eine Nummerierungslücke, hier: 05 ist nicht vorhanden.
Dann bewirkt new_index=4 mit $number >= 5, dass alle 06 zu 05 werden, alle 07 zu 06 usw.

Fall B: Besteht jedoch KEINE Lücke bei 05, so bewirkt
new_index
=4: nix
=5: Ab 05 werden alle Zahlen um -1 (=4-5) niedriger (also um 1 höher).
=3: Ab 05 werden alle Zahlen um 1(=4-3) niedriger.

Ob der Wert 4 hier als Minuend drin vorkommt, weil dies Wert um 1 kleiner als 5 (der Wert von Number) ist, weiß ich nicht. Aber für alle meine Fälle passt das.

Nun allgemein:
Fall A: Nummerierungslücke bei L, dann setze
"$number >= L" und "new_index=L-1"

Fall B:
Alle Zahlen ab N sollen um K erniedrigt werden, dann setze
"$number >= N" und "new_index=N-1-K"
 
  • Gefällt mir
Reaktionen: oglimmer
Zurück
Oben Unten