Skript bzw. Befehl zum Ersetzen von Zeichen in Dateinamen
Re: Skript bzw. Befehl zum Ersetzen von Zeichen in Dateiname
Danke, Newdeb!
Noch zwei Fragen:
1. Gibt es eine Möglichkeit, das erste Zeichen einer Dateibezeichnung spezifisch anzusprechen, zum Beispiel wenn man am Anfang der Bezeichnung andere Zeichen hinzufügen möchte?
2. kann der Befehl rekursiv auf Unterverzeichnisse angewedet werden? Wenn ja, wie soll der Befehl genau aussehen?
Herzlichen Dank
che
Noch zwei Fragen:
1. Gibt es eine Möglichkeit, das erste Zeichen einer Dateibezeichnung spezifisch anzusprechen, zum Beispiel wenn man am Anfang der Bezeichnung andere Zeichen hinzufügen möchte?
2. kann der Befehl rekursiv auf Unterverzeichnisse angewedet werden? Wenn ja, wie soll der Befehl genau aussehen?
Herzlichen Dank
che
-
- Beiträge: 134
- Registriert: 03.02.2011 11:11:21
- Lizenz eigener Beiträge: MIT Lizenz
- Wohnort: Frankfurt
Re: Skript bzw. Befehl zum Ersetzen von Zeichen in Dateiname
Den Wort-/Namensanfang kannst du mit dem Zeichen '^' ansprechen, einen sogenannten Anker (eine gedachte, nicht druckbare Positionsreferenz in einem regulären Ausdruck).
Du kannst auch '^' mit nachfolgenden (Meta-)Zeichen kombinieren, um z.B. das erste Zeichen zu ersetzen ('.' -> beliebiges Zeichen im regulären Ausdruck)
Code: Alles auswählen
$ touch foo
$ rename -n 's/^/my/' foo
foo renamed as myfoo
Code: Alles auswählen
$ touch bar
$ rename -n 's/^./my.t/' bar
bar renamed as my.tar
Zuletzt geändert von Meillo am 03.02.2015 22:20:25, insgesamt 1-mal geändert.
Grund: s/°/^/
Grund: s/°/^/
Re: Skript bzw. Befehl zum Ersetzen von Zeichen in Dateiname
Danke, Newdeb! Das ist genau was ich brauchte! Für die Frage 2 habe ich auf diese Seite interessante Beispiele gefunden, habe sie aber noch nicht ausprobiert:
http://forum.ubuntuusers.de/topic/verze ... nd-rename/
Viele Grüße
che
http://forum.ubuntuusers.de/topic/verze ... nd-rename/
Viele Grüße
che
-
- Beiträge: 134
- Registriert: 03.02.2011 11:11:21
- Lizenz eigener Beiträge: MIT Lizenz
- Wohnort: Frankfurt
Re: Skript bzw. Befehl zum Ersetzen von Zeichen in Dateiname
Ich würde die Antwort in diesem (deinem) Thread nehmen, die ist jüngeren DatumsChe hat geschrieben:Für die Frage 2 habe ich auf diese Seite interessante Beispiele gefunden,
Meillo hat geschrieben:Code: Alles auswählen
find /path/to/dir | xargs rename 's/ä/ae/g'
Re: Skript bzw. Befehl zum Ersetzen von Zeichen in Dateiname
Danke für den Hinweis! Wende ich den Befehl an, bekomme ich die Meldung:
Mit diesem Befehl war es möglich, durch die zahlreichen Unterverzeichnisse durch zu kommen, ohne auf unerwarteten Zeichen hängen zu bleiben:
Was in diesem Unterverzeichnis liegt:
wird mit diesem Befehl:
jedoch nicht entsprechend geändert. Ausgegeben wird die Meldung "Datei oder Verzeichnis nicht gefunden". Leerzeichen im Verzeichnisname dürfen anscheinend nicht vorkommen.
Warum es problematisch ist, wenn im Pfad Großbuchstaben vorkommen (es wird im oben geposteten Link angesprochen) habe ich nicht verstanden. Mit dem relativen Pfad ./ gibt es derartige Probleme nicht. Auf der erwähnten Seite wird diesen zusammengestellten Befehl angegeben:
Wie kann ich das Ende einer Datei-Bezeichnung ansprechen? Gibt es eine Möglichkeit, nur Verzeichnisse bzw. nur Dateien (in den Unterverzeichnissen) anzusprechen? Zu einigen dieser Fragen habe ich hier unter Einsatz des Programms convmv was finden können: https://www.sebastian-siebert.de/2009/1 ... mbenennen/
Um Unterverzeichnisse umzubenennen (z.B. um die Leerzeichen durch anderes Zeichen zu ersetzen, um somit die dort enthaltenen Dateien umbenennen zu können), habe ich erfolgreich folgenden Befehl benutzt:
Für jede Verzeichnisebene muss der Befehl anscheinend erneut ausgeführt werden, er wirkt Schrittweise immer eine Ebene tiefer. Erst danach kann der Befehl um die enthaltenen Dateinamen zu ändern ausgeführt (eventuell auch mehrfach) werden.
Folgende Erläuterungen fand ich hilfreich:
Erläuterung für find:
./ = In welchem Verzeichnis soll durchsucht werden (hier nur aktuelles)
-type f = Nur Dateien sollen berücksichtigt werden
-print0 = Jede Datei wird ein NULL-Zeichen als Trennzeichen angehängt, somit lassen sich die Dateiennamen bei der Übergabe an xargs besser auseinander halten
Erläuterung für xargs:
-r = nicht ausführen, wenn keine weiteren Argumente übergeben werden können (= leer)
-0 = NULL-Zeichen als Trennzeichen berücksichtigen.
Vielen Dank
che
Code: Alles auswählen
find /path/to/dir | xargs rename 's/ä/ae/g'
xargs: unmatched einfache quote; by default quotes are special to xargs unless you use the -0 option
Code: Alles auswählen
find ./ -execdir rename 's/ä/ae/;s/ü/ue/;s/ö/oe/' -v {} \;
Code: Alles auswählen
patricia_shaw/Patrici_Shaw_Gelese_von_Philipp_Schepmann-1/Im_Tal der Mangobaume
01 - Titelnummer 1.ogg
02 - Titelnummer 2.ogg
Code: Alles auswählen
find ./ -execdir rename 's/_-_ /_/;s/ä/ae/;s/ö/oe/;s/ü/ue/;s/Ä/ae/;s/, /_/;s/\._/_/;s/_-_/_/;s/ - /_/;s/ /_/' -v {} \;
Warum es problematisch ist, wenn im Pfad Großbuchstaben vorkommen (es wird im oben geposteten Link angesprochen) habe ich nicht verstanden. Mit dem relativen Pfad ./ gibt es derartige Probleme nicht. Auf der erwähnten Seite wird diesen zusammengestellten Befehl angegeben:
Code: Alles auswählen
find ./ -execdir rename 's/ä/ae/;s/ü/ue/;s/ö/oe/' -v {} \;
Um Unterverzeichnisse umzubenennen (z.B. um die Leerzeichen durch anderes Zeichen zu ersetzen, um somit die dort enthaltenen Dateien umbenennen zu können), habe ich erfolgreich folgenden Befehl benutzt:
Code: Alles auswählen
find ./ -depth -type d -print0 | xargs -r -0 rename 's/\ /_/g'
Folgende Erläuterungen fand ich hilfreich:
Erläuterung für find:
./ = In welchem Verzeichnis soll durchsucht werden (hier nur aktuelles)
-type f = Nur Dateien sollen berücksichtigt werden
-print0 = Jede Datei wird ein NULL-Zeichen als Trennzeichen angehängt, somit lassen sich die Dateiennamen bei der Übergabe an xargs besser auseinander halten
Erläuterung für xargs:
-r = nicht ausführen, wenn keine weiteren Argumente übergeben werden können (= leer)
-0 = NULL-Zeichen als Trennzeichen berücksichtigen.
Vielen Dank
che
Re: Skript bzw. Befehl zum Ersetzen von Zeichen in Dateiname
Hallo Debianer,
wie könnte ich den Ersetzungsbefehl so gestallten, dass alles, was kein Groß- oder Kleinbuchstabe ist und was keine Zahl ist durch "_" ersetzt wird?
Heute wollte ich eine BRD-ISO erstellen und K3B gab die meldung aus:
"/usr/bin/genisoimage: No such file or directory. Invalid node - '/pfad/Datei' "
Dabei habe ich festgestellt, dass ein komisches Viereckzeichen in der angegebenen Dateiname enthalten ist. Dieses Zeichen wird nur sichtbar, wenn man z.B. unter Nautilus das Umbebenne derselben aktiviert hat. Es handelt sich um eine aus dem Internet heruntergeladene Datei.
Das so viele unerwarteten für das Programm unersträglichen Zeichen vorkommen können, wäre es vermutlich einfacher, ein Befehl zu schreiben, der nur die Zeichen angibt, de erlaubt sind, und alles davon abweichende in "_" umwandelt. Geht das? Wie würde sowas aussehen?
Vielen Dank!
che
wie könnte ich den Ersetzungsbefehl so gestallten, dass alles, was kein Groß- oder Kleinbuchstabe ist und was keine Zahl ist durch "_" ersetzt wird?
Heute wollte ich eine BRD-ISO erstellen und K3B gab die meldung aus:
"/usr/bin/genisoimage: No such file or directory. Invalid node - '/pfad/Datei' "
Dabei habe ich festgestellt, dass ein komisches Viereckzeichen in der angegebenen Dateiname enthalten ist. Dieses Zeichen wird nur sichtbar, wenn man z.B. unter Nautilus das Umbebenne derselben aktiviert hat. Es handelt sich um eine aus dem Internet heruntergeladene Datei.
Das so viele unerwarteten für das Programm unersträglichen Zeichen vorkommen können, wäre es vermutlich einfacher, ein Befehl zu schreiben, der nur die Zeichen angibt, de erlaubt sind, und alles davon abweichende in "_" umwandelt. Geht das? Wie würde sowas aussehen?
Vielen Dank!
che
-
- Beiträge: 134
- Registriert: 03.02.2011 11:11:21
- Lizenz eigener Beiträge: MIT Lizenz
- Wohnort: Frankfurt
Re: Skript bzw. Befehl zum Ersetzen von Zeichen in Dateiname
Code: Alles auswählen
rename 's/[^[:alnum:].]/_/g' datei ...
Re: Skript bzw. Befehl zum Ersetzen von Zeichen in Dateiname
Danke! Wenn ich jedoch diesen Befehl so ausführe:
Bekomme ich als Ausgabe eine Reihe von Meldungen wie diese:
Viele Grüße
che
Code: Alles auswählen
rename 's/[^[:alnum:].]/_/g' /media/che/Home-wheezy-sda3/che/Dokumente/*
Code: Alles auswählen
Can't rename /media/che/Home-wheezy-sda3/che/Dokumente/Unternehmen.odt _media_che_Home_wheezy_sda3_che_Dokumente_Unternehmen.odt: Ungültiger Link über Gerätegrenzen hinweg
che
Re: Skript bzw. Befehl zum Ersetzen von Zeichen in Dateiname
Tja, da haette man in der Implementierung statt rename(2) wohl besser mv(1) verwendet (bzw. dessen Vorgehen implementiert) ...Che hat geschrieben:Code: Alles auswählen
rename
Code: Alles auswählen
Ungültiger Link über Gerätegrenzen hinweg
Use ed once in a while!
Re: Skript bzw. Befehl zum Ersetzen von Zeichen in Dateiname
Was hat das zu bedeuten? Wieso "über Gerätegrenzen hinweg", wenn im angegebenen Pfad eine normal heruntergeladene Webseite liegt? Sind vielleicht die darin befindlichen Verlinkungen gemeint?
Entschuldigung, aber ich verstehe nicht wirklich, was du sagen willst.
Als ich weiter oben meinte, dass ein Befehl zur Umbenennung von Dateien und Verzeichnisse, der alle Buchstaben und alle Zahlen beibehalten würde und alles andere durch "_" ersetzt, habe ich auch Buchstaben mit Umlauten oder andere Diakritica als Buchstabe berechnet. Bei dem obigen Befehl scheinen Umlaute aber anders aufgafasst zu werden, denn "Einkäufe" wird zu "Eink__ufe". Wie kann das Berücksichtigt werden?
Viele Grüße
che
Code: Alles auswählen
Tja, da haette man in der Implementierung statt rename(2) wohl besser mv(1) verwendet (bzw. dessen Vorgehen implementiert)
Als ich weiter oben meinte, dass ein Befehl zur Umbenennung von Dateien und Verzeichnisse, der alle Buchstaben und alle Zahlen beibehalten würde und alles andere durch "_" ersetzt, habe ich auch Buchstaben mit Umlauten oder andere Diakritica als Buchstabe berechnet. Bei dem obigen Befehl scheinen Umlaute aber anders aufgafasst zu werden, denn "Einkäufe" wird zu "Eink__ufe". Wie kann das Berücksichtigt werden?
Viele Grüße
che
Re: Skript bzw. Befehl zum Ersetzen von Zeichen in Dateiname
/media und . werden auf verschiedenen Dateisystemen liegen. rename(1) scheint intern den Systemcall rename(2) zu verwenden. Der wirft aber in diesem Fall den Fehler EXDEV (siehe Manpage). Dieser fuehrt zu dieser Fehlermeldung. Wenn ueber Dateisysteme hinweg verschoben werden soll, dann muss kopiert und anschliessend die Quelle geloescht werden.Che hat geschrieben:Was hat das zu bedeuten? Wieso "über Gerätegrenzen hinweg",
Vielleicht solltest du dir am einfachsten ein anderes Rename-Programm suchen, das auch ueber Dateisystemgrenzen hinweg verschieben kann.
Use ed once in a while!
Re: Skript bzw. Befehl zum Ersetzen von Zeichen in Dateinamen
Mal wieder bin ich dabei, Dateien- und Verzeichnisbezeichungen von unerwünschten Zeichen zu befreien. Schade, dass man sich aus Zeitmangel nicht wirklich tief einarbeiten kann.
Mit folgenden drei Befehlen, die großteils aus den Beiträgen von Euch stammen, konnte ich wirklich alles wie gewünscht ersetzen:
1. Muss mehrfach ausgeführt werden, bis alles ersetzt ist:
2. Eine Ausführung reicht. Der Befehl "1." soll unbedingt vorher erfolgreich angewandt worden sein, sonst werden z.B. Zeichen mit Umlaut hier durch "_" ersetzt:
Nur schade, dass ich diesen Befehl bisher nicht zum rekursiven Verhalten überreden konnte, Grund warum ich ihn in jefem Unterverzeichnis extra ausführen muss. Kennt jemand eine Lösung dafür?
3. Verbleibende "." und mehrfach nebeneinander stehende "_" werden hiermit auf einem einzigen "_" versetzt:
Noch offene Wüsche:
1. Jedem Befehl bei der Ausführung mitteilen, wie oft er ausgeführt werden soll. Vor allem beim 1. muss man mehrfach den Vorgang wiederholen. Da würde ich gerne ihm sagen können, mache jetzt 10 Durchläufe und dann höre auf.
2. Dann die drei Befehle in einer einzigen Zeile packen (mein Wunsch "1." berücksichtigt), sodass der Befehl-Bündel nur einmal ausgeführt werden müsste. Das würde sehr hilfreich sein
Viele Grüße
che
Mit folgenden drei Befehlen, die großteils aus den Beiträgen von Euch stammen, konnte ich wirklich alles wie gewünscht ersetzen:
1. Muss mehrfach ausgeführt werden, bis alles ersetzt ist:
Code: Alles auswählen
find ./ -execdir rename 's/ä/ae/;s/ö/oe/;s/ü/ue/;s/Ä/Ae/;s/Ö/Oe/;s/Ü/Ue/;s/ß/ss/;s/é/e/;s/ó/o/;s/í/i/;s/ú/u/;s/á/a/;s/ã/a/;s/Ê/E/;s/ê/e/;s/à/a/;s/è/e/;s/â/a/;s/õ/o/;s/ô/o/;s/Á/A/;s/Ò/O/;s/Ã/A/' -v {} \;
Code: Alles auswählen
rename 's/[^[:alnum:].]/_/g' *
3. Verbleibende "." und mehrfach nebeneinander stehende "_" werden hiermit auf einem einzigen "_" versetzt:
Code: Alles auswählen
find ./ -execdir rename 's/\.\_/\_/;s/\_\_/\_/' -v {} \;
1. Jedem Befehl bei der Ausführung mitteilen, wie oft er ausgeführt werden soll. Vor allem beim 1. muss man mehrfach den Vorgang wiederholen. Da würde ich gerne ihm sagen können, mache jetzt 10 Durchläufe und dann höre auf.
2. Dann die drei Befehle in einer einzigen Zeile packen (mein Wunsch "1." berücksichtigt), sodass der Befehl-Bündel nur einmal ausgeführt werden müsste. Das würde sehr hilfreich sein
Viele Grüße
che
Zuletzt geändert von Che am 12.05.2019 01:36:18, insgesamt 1-mal geändert.
Re: Skript bzw. Befehl zum Ersetzen von Zeichen in Dateinamen
Zunächst mal bin ich der Meinung, dass solche Endlos-Threads eigentlich keine gute Idee sind.
1. ersetzt sowas
nur das erste Vorkommen von ä im Dateinamen. Hat der Dateiname 3 ä im Namen, dann musst du die Routine 3 mal laufen lassen. Abhilfe schafft die globale Ersetzung:
Für einzelne Zeichen (im Such- und Erstzungsabschnitt) bietet sich die y///-Erstzung an, welche nach der Position im Abschnitt das entsprechende Pendant, direkt global ersetzt. Wird ein Zeichen durch 2 Zeichen ersetzt, oder andersrum, dann bleibt lediglich s///g.
2. liegt das an der Funktionsweise von find. Dir wird vermutlich aufgefallen sein, dass dort häufiger "Verzeichnis nicht gefunden" (oder Vergleichbares) aufgetreten ist. Find erstellt in einem Rutsch diese Liste und bearbeitet sie dann von oben nach unten ab. Meinetwegen wäre die Ergebnisliste sowas:
Dann würde das erste rename das Verzeichnis "./Ä" ändern und das danach folgende rename würde aber die Datei "./Ä/ä.txt" nicht finden, da das Verzeichnis ja inzwischen umbenannt wurde und gar nicht mehr existiert. Der nächste Find-Lauf würde dann die Datei "./Ae/ä.txt" finden und rename würde ändern. Was du benötigst wäre eine Ausgabeliste in dieser Form:
Dass die Dateien vor den Verzeichnissen ausgegeben werden, damit die Abarbeitung von oben nach unten durchlaufen kann. Das erreichst du durch den find-Parameter "-depth".
Wenn man das alles kombiniert und zusätzlich noch den Verbose-Schalter von rename an die richtige Stelle setzt (damit du auch was siehst) und dann noch den Turbo von find zündet, in dem man rename eine Argumentliste (+ anstatt \;) übergibt und damit nur insgesamt einen (sofern die Liste nicht zu lang ist), anstatt für jeden Dateinamen einen eigenen Rename-Prozess startet, dann sollte sowas in einem Rutsch performant durchlaufen:
EDIT:
Die letzte Variante funktioniert natürlich nicht, wenn rename im 1. execdir angewendet wurde, da der dann aktuelle Dateiname ja nicht mehr in der Ergebnisliste auftaucht.
Das liegt an 2 Punkten:Che hat geschrieben:11.05.2019 03:03:271. Muss mehrfach ausgeführt werden, bis alles ersetzt ist:Code: Alles auswählen
find ./ -execdir rename 's/ä/ae/;s/ö/oe/;s/ü/ue/;s/Ä/Ae/;s/Ö/Oe/;s/Ü/Ue/;s/ß/ss/;s/é/e/;s/ó/o/;s/í/i/;s/ú/u/;s/á/a/;s/ã/a/;s/Ê/E/;s/ê/e/;s/à/a/;s/è/e/;s/â/a/;s/õ/o/;s/ô/o/;s/Á/A/;s/Ò/O/;s/Ã/A/' -v {} \;
1. ersetzt sowas
Code: Alles auswählen
rename 's/ä/ae/'
Code: Alles auswählen
rename 's/ä/ae/g'
2. liegt das an der Funktionsweise von find. Dir wird vermutlich aufgefallen sein, dass dort häufiger "Verzeichnis nicht gefunden" (oder Vergleichbares) aufgetreten ist. Find erstellt in einem Rutsch diese Liste und bearbeitet sie dann von oben nach unten ab. Meinetwegen wäre die Ergebnisliste sowas:
Code: Alles auswählen
./Ä
./Ä/ä.txt
Code: Alles auswählen
./Ä/ä.txt
./Ä
Wenn man das alles kombiniert und zusätzlich noch den Verbose-Schalter von rename an die richtige Stelle setzt (damit du auch was siehst) und dann noch den Turbo von find zündet, in dem man rename eine Argumentliste (+ anstatt \;) übergibt und damit nur insgesamt einen (sofern die Liste nicht zu lang ist), anstatt für jeden Dateinamen einen eigenen Rename-Prozess startet, dann sollte sowas in einem Rutsch performant durchlaufen:
Code: Alles auswählen
find ./ -depth -execdir rename -v 's/ä/ae/g;s/ö/oe/g;s/ü/ue/g;s/Ä/Ae/g;s/Ö/Oe/g;s/Ü/Ue/g;s/ß/ss/g;y/éóíúáãÊêàèâõôÁÒÃ/eoiuaaEeaeaooAOA/' {} +
Das funktioniert deswegen nicht, weil rename nicht rekursiv arbeitet, sondern nur die Argumente bearbeitet, die du übergibst (hier mit * die Dateien im aktuellen Verzeichnis). Man könnte die Argumente also ebenfalls mit find übergeben. Bei sowas wäre ich allerdings ziemlich vorsichtig, denn hier werden unterschiedliche Zeichen durch ein einziges Zeichen ersetzt, was womöglich Dubletten erzeugen will und damit Fehler hervorrufen dürfte.2. Eine Ausführung reicht. Der Befehl "1." soll unbedingt vorher erfolgreich angewandt worden sein, sonst werden z.B. Zeichen mit Umlaut hier durch "_" ersetzt:Nur schade, dass ich diesen Befehl bisher nicht zum rekursiven Verhalten überreden konnte, Grund warum ich ihn in jefem Unterverzeichnis extra ausführen muss. Kennt jemand eine Lösung dafür?Code: Alles auswählen
rename 's/[^[:alnum:].]/_/g' *
Ein _ muss nicht gequotet werden und im Ersetzungsteil wird alles literal behandelt. Zudem kommt dieses rename ja von Perl, kann also mit + mehrere Zeichen ansprechen:3. Verbleibende "." und mehrfach nebeneinander stehende "_" werden hiermit auf einem einzigen "_" versetzt:Code: Alles auswählen
find ./ -execdir rename 's/\.\_/\_/;s/\_\_/\_/' -v {} \;
Code: Alles auswählen
find ./ -execdir rename -v 's/\._/_/;s/__+/_/' {} +
Sollte obsolet sein!?Noch offene Wüsche:
1. Jedem Befehl bei der Ausführung mitteilen, wie oft er ausgeführt werden soll. Vor allem beim 1. muss man mehrfach den Vorgang wiederholen. Da würde ich gerne ihm sagen können, mache jetzt 10 Durchläufe und dann höre auf.
Mir ist zwar nicht klar, warum das notwendig sein sollte, aber das gibt's mehrere Möglichkeiten: Du kannst die Befehle durch einen Strichpunkt trennen, dann werden die folgenden Befehle ausgeführt, wenn die davorstehenden Befehle abgearbeitet sind, unabhängig davon, ob erfolgreich oder nicht. Oder du kannst die Befehle mit && verketten, dann wird der folgende Befehl abgearbeitet, wenn der davorstehende Befehl erfolgreich (fehlerlos) abgearbeitet wurde. Oder in find direkt - find verkettet automatisch und wenn nicht anders angegeben mittels UND. Bedeutet, dass du einfach die sich unterscheidenden Teile (die -execdir) hintereinander aufführst:2. Dann die drei Befehle in einer einzigen Zeile packen (mein Wunsch "1." berücksichtigt), sodass der Befehl-Bündel nur einmal ausgeführt werden müsste. Das würde sehr hilfreich sein
Code: Alles auswählen
find ... +; find ... +
find ... + && find ... +
find ... -execdir ... + -execdir ... +
Die letzte Variante funktioniert natürlich nicht, wenn rename im 1. execdir angewendet wurde, da der dann aktuelle Dateiname ja nicht mehr in der Ergebnisliste auftaucht.
Re: Skript bzw. Befehl zum Ersetzen von Zeichen in Dateinamen
Viellen Dank für Deine ausführliche und sehr nützliche Antwort
Viele Grüße
che
Viele Grüße
che