staging.inyokaproject.org

Verständnisfrage zum Massenumbenennen

Status: Gelöst | Ubuntu-Version: Lubuntu 18.04 (Bionic Beaver)
Antworten |

Rosika

Anmeldungsdatum:
26. Februar 2016

Beiträge: 1359

Hallo zusammen,

ich hätte eine Verständnisfrage bzgl. Massenumbenennen von Dateinamen mit dem Terminal.

Vorweg: ich weiß, daß es für solche Zwecke das Programm rename für die Kommandozeile gibt, aber mich interessiert die Methode mit sed.

Hintergrund:

Ich habe aus alter Zeit einen Ordner mit einer Reihe von Tondateien, welche ein oder mehrere Leerzeichen im Dateinamen haben. Diese Leerzeichen möchte ich durch einen Unterstrich ersetzen und dabei die Methode mit "sed" nutzen.

Auf der Seite https://stackoverflow.com/questions/2709458/how-to-replace-spaces-in-file-names-using-a-bash-script fand ich eine tolle Anweisung dazu, welche auch gut funktioniert:

for f in *\ *; do mv "$f" "${f// /_}"; done

Ich möchte aber gerne die Syntax komplett verstehen; und da hapert es etwas.

Was ich verstehe (glaube ich zumindest), ist der Teil

${f// /_}

Dieser Teil nutzt also die Parameter-Expansion zur Ersetzung.

Der doppelte Schrägstrich sorgt dafür, daß alle Leerzeichen durch Unterstriche ersetzt werden (und nicht nur beim ersten Vorkommen). Soweit ist´s klar, denke ich.

Es ist der erste Teil, den ich syntaxmäßig nicht verstehe:

for f in *\ *

Warum genügt nicht "for f in"? Und wie genau ist das "*\ * zu verstehen?

Vielen Dank im voraus für Eure Hilfe.

LG. Rosika ☺

Moderiert von rklm:

Thema auf Wunsch umbenannt um den Titel korrekt zu machen

ChickenLipsRfun2eat Team-Icon

Anmeldungsdatum:
6. Dezember 2009

Beiträge: 12067

Hallo!

*\ * bedeutet, alles, was ein Leerzeichen enthält. Es würde also auf „Datei mit Leerzeichen“ matchen, aber nicht auf „DateiOhneLeerzeichen“. Das Leerzeichen ist dabei escaped, damit die Shell nicht "*" "*" daraus macht, sondern den Ausdruck als einen ansieht.

Rosika

(Themenstarter)

Anmeldungsdatum:
26. Februar 2016

Beiträge: 1359

@ChickenLipsRfun2eat:

Hallo und herzlichen Dank für Deine schnelle Antwort.

Ah, so ist das. D.h. es werden beim Ersetzungsprozeß von vornherein lediglich die Dateien, welche ein Leerzeichen enthalten, berücksichtigt.

Also:

Lied1 vom Monat Mai  # Leerezeichen werden ersetzt
Lied2                # wird erst gar nicht berücksichtigt

Nochmals vielen Dank für die tolle Erklärung. Jetzt hab´ ich wieder etwas dazugelernt.

LG. Rosika ☺

Rosika

(Themenstarter)

Anmeldungsdatum:
26. Februar 2016

Beiträge: 1359

Hi erneut,

in einem zweiten und dritten Schritt möchte ich ich noch die runden Klammern auf und zu durch Unterstriche ersetzen.

Bsp.:

ll
insgesamt 12984
drwxrwxr-x 2 rosika rosika   20480 Okt  4 13:57  ./
drwxr-x--- 5 rosika rosika    4096 Jun  4 12:23  ../
-rwxrwxrwx 1 rosika rosika 3327620 Sep 29  2013 'ABBA___Midnight_Special_(Special_Remix_2012).mp3'*
-rwxrwxrwx 1 rosika rosika 3473571 Sep 29  2013 'Adele_-_Make_You_Feel_My_Love(Itunes_Festival_2011).mp3'*
-rwxrwxrwx 1 rosika rosika 4540311 Sep 29  2013 'Leona_Lewis_Run__Lyric(Video)04.11.2013.mp3'*
-rwxrwxrwx 1 rosika rosika 1896293 Sep 29  2013 'Szécsi_Pál_Egy_szál_harangvirág(Donauwellen).mp3'*
-rwxrwxrwx 1 rosika rosika 4144421 Sep 29  2013 'Höstvisa - YouTube~1.mp3'*
-rwxrwxrwx 1 rosika rosika 3473571 Sep 29  2013  Adele_-_Make_You_Feel_My_Love_Itunes_Festival_2011_.mp3*

Zu diesem Zwecke habe ich die Befehle so abgewandelt:

for f in *\(*; do mv "$f" "${f//\(/_}"; done
for f in *\)*; do mv "$f" "${f//\)/_}"; done

Das hat auch soweit funktioniert.

Ich sehe, auch hier muß die Klammer auskommentiert werden.

Eine Frage noch am Rande:

Wie man oben sieht, listet ll alle Einträge, die entweder ein Leerzeichen oder eine Klammer enthalten, mit 'single quotes' auf. Weißt Du evtl, warum das so ist?

Vielen Dank nochmals für die Hilfe.

LG. Rosika ☺

kB Team-Icon

Supporter, Wikiteam
Avatar von kB

Anmeldungsdatum:
4. Oktober 2007

Beiträge: 9837

Rosika schrieb:

[…] Massenumbenennen von Dateinamen mit dem Terminal […] aber mich interessiert die Methode mit sed.

Mit dem Programm sed kann man den Inhalt von Textdateien verändern, aber nicht den Namen einer Datei.

Rosika

(Themenstarter)

Anmeldungsdatum:
26. Februar 2016

Beiträge: 1359

Hallo kB:

Danke für die Aufklärung.

Da bin ich wohl etwas durcheinander gekommen auf meiner Recherche zu dem Thema.

LG. Rosika ☺

P.S.:

Ich würde ja die Themenüberschrift ändern. Das scheint nachträglich aber nicht möglich zu sein(?).

kB Team-Icon

Supporter, Wikiteam
Avatar von kB

Anmeldungsdatum:
4. Oktober 2007

Beiträge: 9837

Rosika schrieb:

[…] Ich würde ja die Themenüberschrift ändern. Das scheint nachträglich aber nicht möglich zu sein(?).

Melde Deinen Thread und bitte die Moderatoren um Umbenennung.

Rosika

(Themenstarter)

Anmeldungsdatum:
26. Februar 2016

Beiträge: 1359

@kB:

Danke für den Tipp. Hab´s ich gerade gemacht.

LG. Rosika

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13242

kB schrieb:

Mit dem Programm sed kann man den Inhalt von Textdateien verändern, aber nicht den Namen einer Datei.

Aber natürlich kann man sed benutzen, um einen neuen Namen zu generieren, der dann für die Umbenennung genutzt wird.

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17630

Rosika schrieb:

Eine Frage noch am Rande:

Wie man oben sieht, listet ll alle Einträge, die entweder ein Leerzeichen oder eine Klammer enthalten, mit 'single quotes' auf. Weißt Du evtl, warum das so ist?

Einige Zeichen sind eigentlich nicht darstellbar oder nicht eindeutig darstellbar. Ein Blank könnte auch ein Tab sein, je nach dem wo es steht. Zeilenumbrüche im Dateinamen sind erlaubt, sogar form feed (Seitenvorschub, wohl primär zur Druckersteuerung gedacht). Oder bell, das normalerweise ein Glockenzeichen über den Lautsprecher ausgeben würde. Andere, wenn sie im literal auf der Kommandozeile eingegeben werden haben Effekte.

Ich meine es ist noch nicht lange her, dass umschließende Apostrophe benutzt werden, um diese Dateinamen zu markieren.

Beachte auch, dass die öffnenden Apostrophe eine Spalte vor den Dateinamen beginnen, wahrscheinlich um sie optisch von Dateinamen zu unterscheiden, die literale Apostrophe in Spalte 1 enthalten. Wer würde solche Dateinamen nutzen? Gute Frage!

Was macht die Anzeige, wenn man einen Namen mit Apostroph beginnt? Auch eine gute Frage!

Was macht ll?

1
type ll

verrät Dir wahrscheinlich, dass ll ein Alias für ls -l ist - ich habe das bei mir geändert; es ist nicht mehr original.

1
man ls

verweist wohl auf weiterführende Informationen bei info ls, wo auch nichts verraten wird. Ein Studium des Quellcodes könnte noch weiterhelfen.

Nach manchem Experiment fördert eine Auflistung von Dateien mit "oo" im Dateinamen bei mir nun folgendes zu Tage:

1
2
3
4
5
ls *oo* 
"'fo oo'"  'fo oo'  'fo(oo)'  'fo\too'

foo:
foo

so dass man auf die Idee kommen könnte, dass der Output von ls *oo* gleich in der Shell weiterverarbeitet werden kann. Dem ist aber nicht so:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
ls -la $(ls *oo*) 
ls: Zugriff auf "'fo" nicht möglich: Datei oder Verzeichnis nicht gefunden
ls: Zugriff auf "oo'" nicht möglich: Datei oder Verzeichnis nicht gefunden
ls: Zugriff auf 'fo' nicht möglich: Datei oder Verzeichnis nicht gefunden
ls: Zugriff auf 'oo' nicht möglich: Datei oder Verzeichnis nicht gefunden
ls: Zugriff auf 'foo:' nicht möglich: Datei oder Verzeichnis nicht gefunden
-rw-rw-r-- 1 stefan stefan    0 Okt  5 03:27 'fo(oo)'
-rw-rw-r-- 1 stefan stefan    0 Okt  5 03:20 'fo\too'

foo:
insgesamt 1352
drwxrwxr-x  3 stefan stefan    4096 Apr 14  2018 .
drwxr-xr-x 25 stefan stefan 1372160 Okt  5 03:38 ..
drwxrwxr-x  3 stefan stefan    4096 Apr 14  2018 foo

Man kann aber mit Copy-and-paste die erste Zeile in ein Kommando pasten:

1
2
3
4
5
ls -la "'fo oo'"  'fo oo'  'fo(oo)'  'fo\too'
-rw-rw-r-- 1 stefan stefan 0 Okt  5 03:38 "'fo oo'"
-rw-rw-r-- 1 stefan stefan 0 Okt  5 03:17 'fo oo'
-rw-rw-r-- 1 stefan stefan 0 Okt  5 03:27 'fo(oo)'
-rw-rw-r-- 1 stefan stefan 0 Okt  5 03:20 'fo\too'

Außer der binären 0, also dem Zeichen mit dem Asciicode 0, nicht das Zeichen 0, und dem Slash ist jedes Zeichen als Teil eines Dateinamens erlaubt. Der Slash ist für die Trennung von Verzeichnissen bzw. Verzeichnissen und anderen Dateien reserviert und die binäre Null markiert das Ende eines Namens.

Alle anderen Zeichen sind erlaubt. Sinnvoll sind nur Kleinbuchstaben, Ziffern, Unter- und der Bindestrich. Alle anderen Zeichen in Dateinamen sind für sadomasochistische Naturen empfehlenswert.

Rosika

(Themenstarter)

Anmeldungsdatum:
26. Februar 2016

Beiträge: 1359

Hallo user_unknown,

herzlichen Dank für Deine ausführliche Antwort (vor allem, wenn ich auf die Uhrzeit sehe 😲 ).

Ich muß gestehen, daß ich Deinen Text gleich mehrere Male durchlesen mußte; aber er ist sehr interessant.

Ich meine es ist noch nicht lange her, dass umschließende Apostrophe benutzt werden, um diese Dateinamen zu markieren.

Ja, da hast Du Recht. Ich denke, die Info, welche ich auf https://superuser.com/questions/1376351/why-does-ls-wrap-some-filenames-in-single-quotes fand, bezieht sich auf Deine Aussage:

ls wraps single quotes around filenames with spaces in them [...]

This was a highly unpopular feature introduced to version 8.25 of the GNU coreutils package as recently as 2016 [...]

the change was at some point reverted after considerable protest, before being once again reinstated in October 2017.

Deine Erklärung ist einleuchtend ("ein Blank könnte auch ein Tab sein"). Soweit habe ich gar nicht gedacht.

dass die öffnenden Apostrophe eine Spalte vor den Dateinamen beginnen

In der Tat. Auch das war mir nicht aufgefallen.

Tatsächlich ist es möglich, mit der Option "-N" das Apostroph-Verhalten zu umgehen, habe ich herausgefunden:

ls --help
[...]
-N, --literal              rohe Eintragsnamen anzeigen (z. B. Kontroll‐
                               zeichen nicht besonders behandeln)
ls
 ABBA___Midnight_Special__Special_Remix_2012_.mp3*
'Adele(Make)You_Feel_My_Love_Itunes_Festival_2011_.mp3'*
 Höstvisa_-_YouTube~1.mp3*
 
ls -N
ABBA___Midnight_Special__Special_Remix_2012_.mp3*
Adele(Make)You_Feel_My_Love_Itunes_Festival_2011_.mp3*
Höstvisa_-_YouTube~1.mp3*

Und noch etwas habe ich - dank Dir - hinzugelernt:

Obgleich ich ls schon lange und oft benutze, wußte ich nicht, daß man (wie in Deinem Beispiel "ls *oo*") damit nach einem Muster suchen kann.

Hat bei mir auch geklappt:

ls *Gre*
Yvan_Rebroff_-_Greensleeves04.13.2013.mp3

Außer der binären 0, also dem Zeichen mit dem Asciicode 0, nicht das Zeichen 0, und dem Slash ist jedes Zeichen als Teil eines Dateinamens erlaubt.

Danke für die zusätzliche Info. Gut zu wissen.

Viel habe ich durch Deinen Post dazugelernt. Wirklich Klasse. Von Deinem Wissen bin ich enorm beeindruckt. 👍 😊

Nochmals allerherzlichsten Dank für die viele Mühe, die Du Dir gegeben hast.

LG. Rosika ☺

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17630

Rosika schrieb:

Nochmals allerherzlichsten Dank für die viele Mühe, die Du Dir gegeben hast.

Keine Ursache. Ich habe Dank Deiner Antwort gelernt, dass es den Schalter -N bei ls gibt, den ich beim Überfliegen der Manpage übersehen habe. Dass es -N ist, werde ich zwar wahrscheinlich vergessen, nicht aber, dass es einen Schalter gibt. ☺

snafu1

Avatar von snafu1

Anmeldungsdatum:
5. September 2007

Beiträge: 2136

Wobei das mit dem "ls *oo*" kein spezielles Verhalten von ls ist, sondern einfach das Expandieren in tatsächliche Dateinamen durch die Shell...

Rosika

(Themenstarter)

Anmeldungsdatum:
26. Februar 2016

Beiträge: 1359

Hi,

@user_unknown:

Habe den Schalter -N selbst erst durch weitere Recherche zu diesem Thema kennen gelernt. Freut mich, daß ich wenigstens etwas (wenn auch wenig) beitragen konnte.

@snafu1:

Danke für die Anmerkung.

Bislang hatte ich immer mit "grep" gesucht, z.B.: "ls | grep Gre". Toll, daß das auch auf die von user_unknown beschriebene Weise funktioniert. Habe danach in den man-pages gesucht, bin aber nicht darauf gestoßen (oder hab´s übersehen 🙄 ).

LG an alle. Rosika ☺

snafu1

Avatar von snafu1

Anmeldungsdatum:
5. September 2007

Beiträge: 2136

Die Sternchen gehören zum Themenbereich Globbing. Hier finden sich eine Menge Beispiele von dem, was mit der Bash möglich ist: https://tldp.org/LDP/abs/html/globbingref.html

Antworten |