Miccovin
Anmeldungsdatum: 9. Februar 2007
Beiträge: 756
|
Hallo Forum, ich habe etliche Dateien in etlichen Ordnern/Unterordnern. In allen Datei- und Ordnernamen sollen (von mir festgelegte) Sonderzeichen durch _ ersetzt werden. Dazu habe ich noch ein paar Spezialfälle, z.B. soll ein & immer in ein + umgewandelt werden. Nun habe ich bisher dieses Anfangsskript: #!/bin/bash
rename 's/\&/+/g' *
rename 's/\(/_/g;s/\)/_/g' *
In der ersten Zeile wird das & mit dem +, in der zweiten Zeile ( und ) mit _ ersetzt. Ich würde das so dann weiter ausbauen. Sehe ich das richtig, dass momentan eine Datei drei mal umbenannt wird, wenn sie &, (, ) enthält? Wenn ja, wie macht man das eleganter - also eine Umbenennung pro Datei/Ordner, die alle Fälle auf einmal berücksichtigt?
Gruß PS: Bisher habe ich das immer mittels pyrenamer gemacht, aber so langsam nervt es, das für jedes Zeichen einzeln machen zu müssen.
|
user_unknown
Anmeldungsdatum: 10. August 2005
Beiträge: 17548
Wohnort: Berlin
|
Miccovin schrieb:
#!/bin/bash
rename 's/\&/+/g' *
rename 's/\(/_/g;s/\)/_/g' *
In der ersten Zeile wird das & mit dem +, in der zweiten Zeile ( und ) mit _ ersetzt. Ich würde das so dann weiter ausbauen. Sehe ich das richtig, dass momentan eine Datei drei mal umbenannt wird, wenn sie &, (, ) enthält? Wenn ja, wie macht man das eleganter - also eine Umbenennung pro Datei/Ordner, die alle Fälle auf einmal berücksichtigt?
Ich denke nein. Das zweite Programm umfasst ja 2 Befehle, und daher vermute ich, ohne den Quellcode von rename studiert zu haben, dass alle Änderungen auf den Namen angewendet werden, und dieser dann umbenannt wird. Die Zeichengruppe, mit Backsteinklammern definiert, erlaubt es aber die Umbenennung zu straffen:
Mit Verkettung von Befehl 1 wird daraus ein Programmaufruf:
| rename 's/\&/+/g;s/[()]/_/g;' *
|
Im Test scheitert der * bei mir an Dateien mit dem Namen 1, daher schlage ich vor stattdessen den Punkt für das akt. Verzeichnis zu nutzen:
| rename 's/\&/+/g;s/[()]/_/g;' .
|
Mit find:exec
| find -depth -type d -exec rename 's/&/+/g;s/[()]/_/g;' . ";"
|
|
Miccovin
(Themenstarter)
Anmeldungsdatum: 9. Februar 2007
Beiträge: 756
|
Erstmal danke. user unknown schrieb: Im Test scheitert der * bei mir an Dateien mit dem Namen 1, daher schlage ich vor stattdessen den Punkt für das akt. Verzeichnis zu nutzen:
| rename 's/\&/+/g;s/[()]/_/g;' .
|
Mit . funktioniert das bei mir nicht. Es passiert einfach nichts. Ich bleib vorerst beim *. Wie kann man '`' ansprechen? Habe es mit \'\`\' versucht, aber das geht nicht.
|
user_unknown
Anmeldungsdatum: 10. August 2005
Beiträge: 17548
Wohnort: Berlin
|
Miccovin schrieb: Erstmal danke. user unknown schrieb: Im Test scheitert der * bei mir an Dateien mit dem Namen 1, daher schlage ich vor stattdessen den Punkt für das akt. Verzeichnis zu nutzen:
| rename 's/\&/+/g;s/[()]/_/g;' .
|
Mit . funktioniert das bei mir nicht. Es passiert einfach nichts. Ich bleib vorerst beim *.
Das ist ein Punkt nach einem Leerzeichen, ja? Und das funktioniert nicht? Wieso nicht? Was hast Du für eine Shell?
Wie kann man '`' ansprechen? Habe es mit \'\`\' versucht, aber das geht nicht.
Zum Beispiel in die Gruppe einschließen.
| rename -n 's/\&/+/g;s/[(`)]/_/g;'
|
Wozu benutzt Du den Backslash?
| rename -n 's/`/_/g;' t*
t`d.lst renamed as t_d.lst
|
Vorsicht vor Cargo-Cult-Programmierung.
|
Miccovin
(Themenstarter)
Anmeldungsdatum: 9. Februar 2007
Beiträge: 756
|
user unknown schrieb:
Das ist ein Punkt nach einem Leerzeichen, ja?
Ja
Und das funktioniert nicht? Wieso nicht? Was hast Du für eine Shell?
Das wüsste ich auch gern, warum es nicht geht. Mache das mit dem xfce4-terminal 0.6.3. Aber auch als sh abgespeichert und ausgeführt gehts nicht.
Zum Beispiel in die Gruppe einschließen.
| rename -n 's/\&/+/g;s/[(`)]/_/g;'
|
Ja, für ` geht das. Aber nicht bei den beiden anderen. Egal, ob ich sie einzeln oder alle drei "in die Gruppe einschließe".
Wozu benutzt Du den Backslash?
Das mache ich, weil ich das irgendwo im Netz so gefunden habe und z.B. [, ], {, } auch nur mit Backslash gehen.
|
user_unknown
Anmeldungsdatum: 10. August 2005
Beiträge: 17548
Wohnort: Berlin
|
Miccovin schrieb: user unknown schrieb:
Das ist ein Punkt nach einem Leerzeichen, ja?
Ja
Und das funktioniert nicht? Wieso nicht? Was hast Du für eine Shell?
Das wüsste ich auch gern, warum es nicht geht. Mache das mit dem xfce4-terminal 0.6.3. Aber auch als sh abgespeichert und ausgeführt gehts nicht.
Zum Beispiel in die Gruppe einschließen.
| rename -n 's/\&/+/g;s/[(`)]/_/g;'
|
Ja, für ` geht das. Aber nicht bei den beiden anderen. Egal, ob ich sie einzeln oder alle drei "in die Gruppe einschließe".
Welche beiden anderen? Das Beispiel ist ein Backtick (oder Accent Grave), meinst Du Accent Aigue (?) und Apostroph? Oben in der Gruppe sehe ich keine 3. Hast Du vielleicht ein anderes rename als ich - oben die Bemerkung zu pyrenamer habe ich nicht recht verstanden, bei mir beruht es auf Perl:
| /usr/bin/prename: a /usr/bin/perl -w script, ASCII text executable
|
Wozu benutzt Du den Backslash?
Das mache ich, weil ich das irgendwo im Netz so gefunden habe und z.B. [, ], {, } auch nur mit Backslash gehen.
Ja, das ist wie zu Ostern einen Tannenbaum kaufen, weil es an Weihnachten auch einen gibt. In verschiedenen Sprachen bedeuten verschiedene Zeichen unterschiedliches, und müssen dann vielleicht maskiert werden oder nicht. In einem regulären Guppenausdruck [...] bedeutet eine eckige Klammer zu, dass die Gruppe hier endet - will man die Klammer zu als Zeichen dieser Gruppe zuführen muss sie maskiert werden. Geschweifte Klammern in Gruppen bedeuten aber gar nichts besonderes und müssen daher auch nicht maskiert werden. Außerhalb der Gruppe bedeuten sie schon etwas besonderes und müssen daher dort maskiert werden, aber eben nicht generell überall. Die Gefahr ist groß beim wilden Ausprobieren was falsch zu machen oder auf Dauer viel Zeit dabei zu verlieren.
Es gibt übrigens keinen sinnvollen, regulären Ausdruck (aber Situationen, in denen welche auftauchen könnten), bei dem der Bereich zwischen den eckigen Klammern leer ist. Daher kann man die schließende, eckige Klammer gleich als erstes Zeichen der Gruppe verwenden. Das Programm unterstellt dann, dass, da es ja keinen Sinn macht die Gruppe zu schließen ohne ein Element darin, dass die eckige Klammer selbst in die Gruppe gehören muss. Da man auch Zeichenbereiche spezifizieren kann
| rename 's/[a-f]/_/' foo*
rename 's/[0-9]/_/' foo*
rename 's/[!-/]/_/' foo*
|
ist das Minuszeichen in eckigen Klammern ein spezieller Fall und bedeutet nicht das Zeichen selbst, sondern die Zeichen von a bis f usw. Um das Minuszeichen selbst zu meinen muss man es auch maskieren, oder es als erstes oder letztes Zeichen in die Gruppe packen. Vielleicht ist so eine Gruppe ja auch was für Dich? Die Verteilung der Sonderzeichen sieht so aus:
| (33 to 127).foreach (x=> print (x + " : " + x.toChar + "\t"))
|
| 33 : ! 34 : " 35 : # 36 : $ 37 : % 38 : & 39 : ' 40 : ( 41 : ) 42 : * 43 : + 44 : , 45 : - 46 : . 47 : /
48 : 0 49 : 1 50 : 2 51 : 3 52 : 4 53 : 5 54 : 6 55 : 7 56 : 8 57 : 9
58 : : 59 : ; 60 : < 61 : = 62 : > 63 : ? 64 : @
65 : A 66 : B 67 : C 68 : D 69 : E 70 : F 71 : G 72 : H 73 : I 74 : J 75 : K 76 : L 77 : M 78 : N 79 : O 80 : P81 : Q 82 : R 83 : S 84 : T 85 : U 86 : V 87 : W 88 : X 89 : Y 90 : Z
91 : [ 92 : \ 93 : ] 94 : ^ 95 : _ 96 : `
97 : a 98 : b 99 : c 100 : d 101 : e 102 : f 103 : g 104 : h 105 : i 106 : j 107 : k 108 : l 109 : m 110 : n 111 : o 112 : p 113 : q 114 : r 115 : s 116 : t 117 : u 118 : v 119 : w 120 : x 121 : y 122 : z
123 : { 124 : | 125 : } 126 : ~ 127 :
|
(Umbrüche manuell eingestreut)
|
Miccovin
(Themenstarter)
Anmeldungsdatum: 9. Februar 2007
Beiträge: 756
|
Ich meinte die drei "Apostrophe" oder wie die heissen. Die zwei auf der Taste direkt links von Backspace ' und ` (per SHIFT). Dazu gibt es noch mittels SHIFT + # = '. Wobei der erste und letzte anscheinend dieselben sind? - Ich nutze das rename, das standardmässig bei meinem Xubuntu 14.04 im Terminal verfügbar ist. Keine Ahnung, wie ich Deine Terminal-Angabe zu rename bekomme, vielleicht reicht das:
foo@bar:~$ /usr/bin/prename
Usage: rename [-v] [-n] [-f] perlexpr [filenames] - Es gibt ein Programm names pyrenamer (hat eine Gui). Der Nachteil ist dort, dass man jedes Zeichen einzeln abarbeiten muss - und das nervt auf Dauer. Daher versuche ich mich jetzt hier. (war nur ein kleiner Kommentar - nichts wichtiges) -
Die Gefahr ist groß beim wilden Ausprobieren was falsch zu machen oder auf Dauer viel Zeit dabei zu verlieren.
Wahrscheinlich hab ich beim wilden Ausprobieren tatsächlich was falsch gemacht. Eben gingen {, }, [ jedenfalls problemlos, nur ] muss ich noch "maskieren". Wahrscheinlich meinst Du damit \]? Dann geht z.B. sowas: rename 's/[(){}[\]]/_/g;' * - So ein definierter Zeichenbereich wäre schon praktisch, ja. Aber beim Probieren funktioniert rename 's/[!-/]/_/g;' * nicht. Da sollten doch alle Zeichen von ! (Nr. 33) bis / (Nr. 47) in ein _ geändert werden, oder nicht? Im Terminal sagt er das:
foo@bar:/media/foo/Platte/bla$ ls -l
insgesamt 23748
-rwxrwxrwx 1 trusty root 12465154 Jul 25 20:41 and (wish. bulu)_[tarala]{}.txt
-rwxrwxrwx 1 trusty root 11838253 Jul 25 20:41 C'est _[bla].txt
drwxrwxrwx 1 trusty root 4096 Aug 30 22:09 __gf
-rwxrwxrwx 1 trusty root 948 Aug 30 22:06 um.sh
foo@bar:/media/foo/Platte/bla$ rename 's/[!-/]/_/g;' *
Unmatched [ in regex; marked by <-- HERE in m/[ <-- HERE !-/ at (eval 1) line 1.
foo@bar:/media/foo/Platte/bla$ rename 's/[!-/]/_/g;' .
Unmatched [ in regex; marked by <-- HERE in m/[ <-- HERE !-/ at (eval 1) line 1. Vielleicht kannst Du damit irgendwas anfangen.
|
track
Anmeldungsdatum: 26. Juni 2008
Beiträge: 7174
Wohnort: Wolfen (S-A)
|
Was Du benutzen möchtest, ist ja das Perl- rename. Folglich gilt dafür auch die Perl- Syntax. Allerdings, da Du das ganze über die (Shell-) Commandline eingibst, musst Du ein paar Zeichen noch maskieren, damit die Shell sie nicht vorher interpretiert, sondern blind weiterreicht: track@lucid:~$ echo "\` ´ ' + # ="
` ´ ' + # =
track@lucid:~$ echo "\` ´ ' + # =" | perl -pe "s|[\`´'+#=\!-/]|_|g"
_ __ _ _ _ _ Hier also insbesondere der Backtick ` und das Ausrufezeichen. Allerdings sieht man hier ein typisches Problem von Perl mit utf-8: weil der Perl- s- Befehl byteweise arbeitet, wird der vorwärts- Akzent als 2 Zeichen gesehen: er besteht ja aus [c2 b4], und das sind sowohl in der Eingabe, als auch im s- Befehl einfach nur 2 Bytes, nämlich [c2] und [b4], und jedes davon wird brav in einen Unterstrich umgewandelt (deshalb dort 2 Unterstriche !). Wenn Du diese Hürde vermeidest und nach den Regeln der Kunst maskierst, sollte es gehen, natürlich auch mit Perl- rename. LG, track
|
Miccovin
(Themenstarter)
Anmeldungsdatum: 9. Februar 2007
Beiträge: 756
|
track schrieb: Was Du benutzen möchtest, ist ja das Perl- rename.
Nö. Ich möchte einen Befehl benutzen, mit dem ich umbenennen kann. Wessen rename das jetzt ist, ist mir völlig schnuppe. Auch der eigentliche Befehl ist mir völlig egal. Wenn es mit einem anderen auch oder sogar besser geht - nur her damit! Langsam sollte doch wohl klar sein, dass ich mich damit wenig bis gar nicht auskenne und bei rename bin ich gelandet, weil das halt im Wiki steht. *schulterzuck*
Allerdings, da Du das ganze über die (Shell-) Commandline eingibst
Aha, irgendwo muss ich das ja eingeben. Packe ich das in die sh aus dem ersten Posting, ist es also schon wieder anders? Oder doch nicht? Keine Ahnung. Langsam wird das ganze einfach nur noch frustrierend. Habe mich jetzt schon ein paar Stunden durch zig Tabs gewühlt, aber wirklich was rausgekommen ist bisher nicht. Ich verstehe auch nicht, warum es dazu nichts im Wiki gibt - ich bin doch sicher nicht der erste, der mehrere Sonderzeichen in Dateinamen und Ordnern in einem Rutsch umbenennen will (und nicht immer nur einzelne Zeichen, wie in den Beispielen). Dazu könnte dort gerne mal was rein.
|
user_unknown
Anmeldungsdatum: 10. August 2005
Beiträge: 17548
Wohnort: Berlin
|
Miccovin schrieb:
So ein definierter Zeichenbereich wäre schon praktisch, ja. Aber beim Probieren funktioniert rename 's/[!-/]/_/g;' * nicht. Da sollten doch alle Zeichen von ! (Nr. 33) bis / (Nr. 47) in ein _ geändert werden, oder nicht? Im Terminal sagt er das:
foo@bar:/media/foo/Platte/bla$ ls -l
insgesamt 23748
-rwxrwxrwx 1 trusty root 12465154 Jul 25 20:41 and (wish. bulu)_[tarala]{}.txt
-rwxrwxrwx 1 trusty root 11838253 Jul 25 20:41 C'est _[bla].txt
drwxrwxrwx 1 trusty root 4096 Aug 30 22:09 __gf
-rwxrwxrwx 1 trusty root 948 Aug 30 22:06 um.sh
foo@bar:/media/foo/Platte/bla$ rename 's/[!-/]/_/g;' *
Unmatched [ in regex; marked by <-- HERE in m/[ <-- HERE !-/ at (eval 1) line 1.
foo@bar:/media/foo/Platte/bla$ rename 's/[!-/]/_/g;' .
Unmatched [ in regex; marked by <-- HERE in m/[ <-- HERE !-/ at (eval 1) line 1. Vielleicht kannst Du damit irgendwas anfangen.
Unmatched [ bedeutet, dass die eckige Klammer auf aber nicht zugeht. Das bedeutet, dass das Slash in den eckigen Klammern nicht als Element der Gruppe sondern als Ende des zu findenden Ausdrucks interpretiert wird. Alle Feinheiten habe ich auch nicht im Kopf und muss - entgegen meiner Predigt - dann doch selbst ausprobieren. Es kommt aber zu selten vor, als dass es sich lohnte das zu lernen, und ich schätze ich kann das Risiko von Fehlern einschätzen. Bei 'rename' kann man mit -n ja sehr viele Fehler ausschließen. Es muss also | rename -n "s/[!-\/]/_/g" foo*
|
heißen, also der Slash maskiert werden. Alternativ kann man einen anderen Trenner verwenden:
| rename -n "s|[!-/]|_|g" foo*
|
|
Miccovin
(Themenstarter)
Anmeldungsdatum: 9. Februar 2007
Beiträge: 756
|
Ich machs jetzt doch so, jedes Zeichen einzeln aufzurufen, weil ich sonst mit zu viel Ausnahmen arbeiten müsste und die Zeichenbereiche zu klein werden. Momentan versuche ich mich an find. Das rename soll für alle Dateien des aktuellen Ordners und alle seine Unterordner inklusive ihrer Dateien gelten. Mit dem folgenden werden aber nur die Dateien und Ordner im aktuellen Ordner angesprochen (also auf höchster Ebene) - er geht aber nicht tiefer.
find -depth -type d -exec rename 's/&/+/g' * ";" Wie geht's richtig?
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12801
|
Miccovin schrieb: Ich machs jetzt doch so, jedes Zeichen einzeln aufzurufen, weil ich sonst mit zu viel Ausnahmen arbeiten müsste und die Zeichenbereiche zu klein werden.
Was bedeutet das? Ich habe jetzt nicht den Thread im Detail verfolgt, aber es scheint doch so, dass Du nur den passenden Regulären Ausdruck definieren musst, so dass alle Zeichen, die Du geändert haben willst, durch Unterstriche ersetzt werden. Dazu hast Du doch schon Erklärungen bekommen.
find -depth -type d -exec rename 's/&/+/g' * ";" Wie geht's richtig?
Das wäre fast ein Thema für einen neuen Thread, denn hier geht es um Bedienung von find . ☺ In Deinem Fall musst Du erst mal den Stern weglassen. Dann darfst Du nicht nur nach Ordnern suchen, wenn Du auch Dateien umbenannt haben möchtest. Und Du kannst es noch etwas effizienter machen, indem Du ";" durch + ersetzt. Ciao robert
|
Miccovin
(Themenstarter)
Anmeldungsdatum: 9. Februar 2007
Beiträge: 756
|
rklm schrieb: Was bedeutet das?
user unknown hatte hier ganz unten im Beitrag auf Zeichenbereiche hingewiesen, die ich nehmen könnte. Wenn ich z.B. !-/ nehmen würde, müsste ich aber & und . wieder davon ausnehmen. Da mache ich mir lieber meine eigene Liste, ausserdem sehe dann sofort, was da alles drin ist. Nicht weiter wichtig.
In Deinem Fall musst Du erst mal den Stern weglassen. Dann darfst Du nicht nur nach Ordnern suchen, wenn Du auch Dateien umbenannt haben möchtest. Und Du kannst es noch etwas effizienter machen, indem Du ";" durch + ersetzt.
Ok, ich habe nun den * und type -d rausgeschmissen. Am Schluss jetzt {} "+", auch wenn ich das nicht wirklich verstehe, aber damit scheint es am besten zu klappen. Momentan sieht meine sh so aus:
#!/bin/bash
find -depth -exec rename 's/&/+/g; s/ß/ss/g; s/bla/blubb/g; s/Ä/Ae/g; s/Ö/Oe/g; s/Ü/Ue/g; s/ä/ae/g; s/ö/oe/g; s/ü/ue/g; s/[´`",;~!?#()\{\}[\]]/_/g;' {} "+"
find -depth -exec rename "s/'/_/g" {} "+"
Das zweite find bzw. rename mit den " muss ich haben, damit ich ' umbenennen kann, da ich es ins erste nicht eingebaut bekomme. Dann passiert einfach gar nichts mehr, egal ob ich ' oder \' nehme. Kann ich die zwei find-Befehle jetzt noch miteinander verknüpfen? Mal davon abgesehen, dass so jede Datei / jeder Ordner zwei mal abgeglichen werden: Ich muss die sh auch zwei mal ausführen. Beim ersten mal werden auf höchster Ebene, auf der die sh liegt, alle Dateien und Ordner komplett umbenannt. Im Unterordner wird komischerweise nur das zweite find angewendet, d.h. die ' werden umbenannt, der Rest bleibt. Führe ich die sh jetzt noch einmal aus, wird auch der Unterordner komplettiert. Schon komisch.
|