Es kann zu Problemen kommen, wenn Sie Dateien und Verzeichnisse gleichzeitig umbenennen möchten . Nur eine Datei umzubenennen ist einfach genug. Sie möchten jedoch sicherstellen, dass die Verzeichnisse auch umbenannt werden. Sie können nicht einfach mv Motörhead/Encöding Motorhead/Encoding
da Motorhead
zum Zeitpunkt des Anrufs nicht existieren.
Wir müssen also zuerst alle Dateien und Ordner gründlich durchlaufen und dann nur die aktuelle Datei oder den aktuellen Ordner umbenennen. Das Folgende funktioniert mit GNU find
und Bash 4.2.42 auf meinem OS X.
#!/usr/bin/env bash
find "$1" -depth -print0 | while IFS= read -r -d '' file; do
d="$( dirname "$file" )"
f="$( basename "$file" )"
new="${f//[^a-zA-Z0-9\/\._\-]/}"
if [ "$f" != "$new" ] # if equal, name is already clean, so leave alone
then
if [ -e "$d/$new" ]
then
echo "Notice: \"$new\" and \"$f\" both exist in "$d":"
ls -ld "$d/$new" "$d/$f"
else
echo mv "$file" "$d/$new" # remove "echo" to actually rename things
fi
fi
done
Sie können den regulären Ausdruck ändern, indem Sie verwenden, new="${f//[\\\/\:\*\?\"<>|]/}"
wenn Sie alles ersetzen möchten, was Windows nicht verarbeiten kann.
Speichern Sie dieses Skript als rename.sh
, und machen Sie es mit ausführbar chmod +x rename.sh
. Dann nenne es wie rename.sh /some/path
.
Stellen Sie sicher, dass Kollisionen von Dateinamen (" Notice
" Ansagen) behoben werden.
Wenn Sie absolut sicher sind, dass es die richtigen Ersetzungen vornimmt, entfernen Sie das Symbol echo
aus dem Skript , um die Objekte tatsächlich umzubenennen, anstatt nur zu drucken, was es tut.
Aus Sicherheitsgründen würde ich empfehlen, dies zunächst an einer kleinen Teilmenge von Dateien zu testen.
Optionen erklärt
Um zu erklären, was hier vor sich geht:
-depth
wird sicherstellen, dass Verzeichnisse mit der Tiefe zuerst rekursiv behandelt werden, damit wir alles vom Ende an "zusammenfassen" können. Normalerweise find
wird anders überquert (aber nicht in der Breite zuerst).
-print0
Stellt sicher, dass die find
Ausgabe durch Nullen getrennt ist, damit wir sie read -d ''
in die file
Variable einlesen können . Auf diese Weise können wir mit allen Arten von seltsamen Dateinamen umgehen, auch mit Leerzeichen und sogar mit Zeilenumbrüchen.
- Wir werden das Verzeichnis der Datei mit bekommen
dirname
. Vergessen Sie nicht, Ihre Variablen immer korrekt in Anführungszeichen zu setzen, da sonst ein Pfad mit Leerzeichen oder glühenden Zeichen dieses Skript beschädigen würde.
- Wir erhalten den tatsächlichen Dateinamen (oder Verzeichnisnamen) mit
basename
.
- Anschließend entfernen wir alle ungültigen Zeichen aus der
$f
Verwendung von Bashs Funktionen zum Ersetzen von Zeichenfolgen. Ungültig bedeutet, dass es sich nicht um einen Klein- oder Großbuchstaben, eine Ziffer, einen Schrägstrich ( \/
), einen Punkt ( \.
), einen Unterstrich oder einen Minus-Bindestrich handelt.
- Wenn
$f
es bereits sauber ist (der gereinigte Name ist identisch mit dem aktuellen Namen), überspringen Sie ihn.
- Wenn
$new
das Verzeichnis bereits vorhanden ist $d
(z. B. Sie haben Dateien mit dem Namen resume
und résumé
im selben Verzeichnis), geben Sie eine Warnung aus. Sie möchten es nicht umbenennen, da dies auf einigen Systemen mv foo foo
zu Problemen führt. Andernfalls,
- Wir benennen die ursprüngliche Datei (oder das ursprüngliche Verzeichnis) schließlich in ihren neuen Namen um
Da dies nur auf die tiefste Hierarchie angewendet wird, erfolgt die Umbenennung Motörhead/Encöding
in Motorhead/Encoding
in zwei Schritten:
mv Motörhead/Encöding Motörhead/Encoding
mv Motörhead Motorhead
Dadurch wird sichergestellt, dass alle Ersetzungen in der richtigen Reihenfolge erfolgen.
Beispieldateien und Testlauf
Nehmen wir an, einige Dateien in einem Basisordner mit dem Namen test
:
test
test/Motörhead
test/Motörhead/anöther_file.mp3
test/Motörhead/Encöding
test/Randöm
test/Täst
test/Täst/Töst
test/with space
test/with-hyphen.txt
test/work
test/work/resume
test/work/résumé
test/work/schedule
Hier ist die Ausgabe eines Laufs im Debug-Modus (mit dem echo
vor dem mv
), dh die Befehle, die aufgerufen werden würden, und die Kollisionswarnungen:
mv test/Motörhead/anöther_file.mp3 test/Motörhead/another_file.mp3
mv test/Motörhead/Encöding test/Motörhead/Encoding
mv test/Motörhead test/Motorhead
mv test/Randöm test/Random
mv test/Täst/Töst test/Täst/Tost
mv test/Täst test/Tast
mv test/with space test/withspace
Notice: "resume" and "résumé" both exist in test/work:
-rw-r—r-- … … test/work/resume
-rw-r—r-- … … test/work/résumé
Beachten Sie die Abwesenheit von Nachrichten für with-hyphen.txt
, schedule
und test
selbst.
mv
bereits vorhanden ist. Dies kann passieren (1), wenn Sie Dateien haben, die bereits bereinigt sind (was zu führtmv foo foo
), oder (2), wenn Sie Dateien mit dem gleichen Namen außer haben für die Sonderzeichen (zBmv Encöding Encoding
wo SieEncoding
zusätzlich zuEncöding
).