Vermeiden Sie das Ersetzen von Leerzeichen beim Umbenennen von Dateien

10

Ich versuche, Dateien wie folgt umzubenennen:

for file in *;
do
mv -i "$file" "$(echo "$file" | sed -e 's/[^A-Za-z0-9._-]/_/g')";
done

Der sedBefehl ersetzt jedoch alle Leerzeichen durch _.

Wie kann ich den sedBefehl bearbeiten , um Leerzeichen zusammen mit den angegebenen Zeichen einzuschließen? Ich habe versucht, \saber es funktioniert nicht ...

BEARBEITEN:
Zum Beispiel: Die Datei trip: hillsollte umbenannt werden: trip_ hillaber der obige Befehl macht es trip__hill.

Zanna
quelle
Ich verschiebe einige Dateien von Linux auf den Mac. Aus irgendeinem Grund kann das Mac-System jedoch nicht alle Dateinamen lesen, daher versuche ich, meine Dateien umzubenennen. Das Hinzufügen eines Leerzeichens zum obigen Befehl funktioniert nicht. Und Sie haben Recht: Ich möchte alle Zeichen mit Ausnahme der angegebenen durch '_' ersetzen. Und ich weiß nicht, wie ich das Leerzeichen einfügen soll.
Bitte beachten Sie, dass ich versuche, alle Zeichen mit Ausnahme der angegebenen durch '_' zu ersetzen. Die umbenannten Dateien haben kein bestimmtes Muster, daher kann ich diesen Perl-Befehl nicht verwenden.

Antworten:

11

Analysieren Sie keine Dateinamen mit sed! Die Ausgabe von ist echo "$file"möglicherweise nicht zuverlässig.

Verwenden Sie rename. Am 17.10 müssen Sie es zuerst installieren

sudo apt install rename

Dann:

rename -n -- 's/[^-A-Za-z0-9_ .]/_/g' *

Anmerkungen

  • -nNach dem Testen entfernen , um die Dateien tatsächlich umzubenennen
  • -- Ende der Optionen, falls eine Datei mit beginnt -
  • [^-A-Za-z0-9_ .]Zeichen, die wir nicht ersetzen möchten - setzen Sie -zuerst oder zuletzt, damit kein Bereich angegeben werden kann (dies wird an diesen Positionen wörtlich behandelt).
  • Leerzeichen können in die Klasse aufgenommen werden
  • . wird wörtlich behandelt (in anderen Regex-Kontexten steht es für jedes Zeichen und muss maskiert werden).

Dies funktioniert auch in sed:

$ echo 'trip: hill' | sed 's/[^-A-Za-z0-9 _.]/_/g'
trip_ hill

Wenn ich in Ihrer Version am Ende ein Leerzeichen hinzufüge, wird folgende Fehlermeldung angezeigt:

$ echo 'trip: hill' | sed -e 's/[^A-Za-z0-9._- ]/_/g'
sed: -e expression #1, char 22: Invalid range end

Aber -am Ende funktioniert es:

$ echo 'trip: hill' | sed -e 's/[^A-Za-z0-9._ -]/_/g'
trip_ hill

Vielleicht hat die Position des Bindestrichs Ihr Problem verursacht, als Sie das Leerzeichen hinzugefügt haben. Aber der Rat, Dateinamen nicht zu analysieren, steht!

Zanna
quelle
Dieser Befehl funktioniert danke. Sie haben auch die Fehler in dem von mir verwendeten Befehl klar identifiziert.
2
Danke nochmal. Bitte beachten Sie, dass bei Verwendung von sed kein Schrägstrich '\' erforderlich ist. Weil dies '\' zur Liste der ignorierten Zeichen hinzufügt.
2
@latach Das ist ein Backslash, aber du hast absolut Recht. Nach dem Testen und Herumgraben stellte ich fest, dass dies .in einer Charakterklasse wörtlich ist. BIS!
Zanna
2

Sie können auch einfach die Shell verwenden. Die Parametererweiterung von Bash kann ersetzt werden:

for f in ./* ; do
    mv "$f" "${f//[^-A-Za-z0-9._ ]/_}"
done

Der doppelte Schrägstrich weist ihn an, alle Übereinstimmungen zu ersetzen, ansonsten ist die Syntax unkompliziert.

ilkkachu
quelle