Wie entferne ich ungültige Zeichen aus Dateinamen?

47

Ich habe Dateien mit ungültigen Zeichen wie diesen

009_-_�%86ndringshåndtering.html

Hier ist Æetwas im Dateinamen schief gelaufen.

Gibt es eine Möglichkeit, alle ungültigen Zeichen zu entfernen?

oder könnte trdas irgendwie genutzt werden?

echo "009_-_�%86ndringshåndtering.html" | tr ???
Sandra
quelle
5
Die Zeichen sind wahrscheinlich nicht "ungültig", sonst würde das Dateisystem sie nicht speichern (es sei denn, Sie haben der FS etwas wirklich Schlimmes angetan). Haben Sie versucht, Ihr Gebietsschema zu ändern (z. B. auf UTF8), um die Namen korrekt anzuzeigen?
James O'Gorman

Antworten:

41

Ein Weg wäre mit sed:

mv 'file' $(echo 'file' | sed -e 's/[^A-Za-z0-9._-]/_/g')

Ersetzen fileSie sie natürlich durch Ihren Dateinamen. Dies ersetzt alles, was kein Buchstabe, Ziffer, Punkt, Unterstrich oder Bindestrich ist, durch einen Unterstrich. Sie können Zeichen hinzufügen oder entfernen, um sie beizubehalten, und / oder das Ersatzzeichen in etwas anderes oder gar nichts zu ändern.

James Sneeringer
quelle
4
Ich verwendete:f='file'; mv 'file' ${f//[^A-Za-z0-9._-]/_}
Louis
1
Suchen Sie nach der besten Lösung von H. Hess unten ... (und meinem lustigen Kommentar neben :))
Jan Sila
31

Ich gehe davon aus, dass Sie auf einer Linux-Box sind und die Dateien auf einer Windows-Box erstellt wurden. Linux verwendet UTF-8 als Zeichenkodierung für Dateinamen, während Windows etwas anderes verwendet. Ich denke, das ist die Ursache des Problems.

Ich würde "convmv" verwenden. Dies ist ein Tool, das Dateinamen von einer Zeichenkodierung in eine andere konvertieren kann. Für Westeuropa funktioniert normalerweise eines der folgenden Verfahren:

convmv -r -f windows-1252 -t UTF-8 .
convmv -r -f ISO-8859-1 -t UTF-8 .
convmv -r -f cp-850 -t UTF-8 .

Wenn Sie es auf einem Debian-basierten Linux installieren müssen, können Sie dies tun, indem Sie Folgendes ausführen:

sudo apt-get install convmv

Es funktioniert bei mir jedes Mal und stellt den ursprünglichen Dateinamen wieder her.

Quelle: LeaseWebLabs

mevdschee
quelle
1
Das sieht vielversprechend aus, aber gibt es eine Idee, wie man die Codierung erkennt? Ich habe ein Verzeichnis mit dem Namen Save the current file in Word 97-2004 format\sco.workflow, das auf meinem Mac erstellt wurde (über Microsoft Office), und die obigen Codierungen haben keine Auswirkung.
Sridhar Sarnobat
Es ist erwähnenswert, dass convmv standardmäßig im "Test" -Modus ausgeführt wird, in dem nur ein Probelauf ausgeführt wird und Sie darüber informiert werden, welche Dateien verschoben werden sollen. Anschließend werden Sie aufgefordert, das Programm erneut auszuführen und --notestdie Dateien umzubenennen.
Kenny Rasschaert
16

Ich nehme an, Sie meinen, Sie möchten das Dateisystem durchqueren und alle diese Dateien reparieren?

So würde ich es machen

find /path/to/files -type f -print0 | \
perl -n0e '$new = $_; if($new =~ s/[^[:ascii:]]/_/g) {
  print("Renaming $_ to $new\n"); rename($_, $new);
}'

Das würde alle Dateien mit Nicht-ASCII-Zeichen finden und diese Zeichen durch Unterstriche ( _) ersetzen . Seien Sie jedoch vorsichtig, wenn eine Datei mit dem neuen Namen bereits vorhanden ist, wird sie überschrieben. Das Skript kann geändert werden, um nach einem solchen Fall zu suchen, aber ich habe das nicht eingefügt, um es einfach zu halten.

Patrick
quelle
13

Die folgenden Antworten finden Sie unter https://stackoverflow.com/questions/2124010/grep-regex-to-match-non-ascii-characters . Sie können Folgendes verwenden:

rename 's/[^\x00-\x7F]//g' *

wo *passt zu den Dateien, die Sie umbenennen möchten. Wenn Sie es über mehrere Verzeichnisse tun möchten, können Sie Folgendes tun:

find . -exec rename 's/[^\x00-\x7F]//g' "{}" \;

Mit dem Argument -n können renameSie einen Probelauf durchführen und sehen, was geändert wird, ohne es zu ändern.

naught101
quelle
Gibt es eine Möglichkeit, dies zu ändern, um fremde Zeichen wie ü und ä beizubehalten?
Elder Geek
Nur der zweite hat für mich gearbeitet. Alles war im selben Verzeichnis, also bin ich mir nicht sicher, was der Unterschied ist.
Shautieh
1
@Shautieh: das -n stoppt es tatsächlich am Laufen. Ich werde die Antwort klären.
Naught101
Das Umbenennen kann beim Umgang mit vielen Dateien langsam sein. Wenn Sie dies beschleunigen möchten, drücken Sie den Scheck in find. Ich bin mir allerdings nicht sicher, wie ich das machen soll.
Isaaclw
13

Ich hatte einige japanische Dateien mit kaputten Dateinamen von einem kaputten USB-Stick wiederhergestellt und die oben genannten Lösungen funktionierten nicht für mich.

Ich empfehle das Detox-Paket:

Das Dienstprogramm detox benennt Dateien um, um die Arbeit mit ihnen zu erleichtern. Es beseitigt Leerzeichen und andere derartige Belästigungen. Es werden auch Latin-1-Zeichen (ISO 8859-1), die in 8-Bit-ASCII codiert sind, Unicode-Zeichen, die in UTF-8 codiert sind, und CGI-Escape-Zeichen übersetzt oder bereinigt.

Anwendungsbeispiel:

detox -r -v /path/to/your/files
-r In Unterverzeichnisse zurückverfolgen
-v Ausführlich darüber sein, welche Dateien umbenannt werden 
-n Kann für einen Trockenlauf verwendet werden (nur anzeigen, was geändert werden würde)
H. Hess
quelle
2
Das sollte viel höher sein, ich fordere jeden auf, sich detoxdas Rad anzuschauen, bevor er es grundlegend neu erfindet. Wenn Sie sich die Manpage ansehen, werden Sie feststellen, dass sie aufgrund ihrer Flexibilität alle anderen hier vorgeschlagenen Lösungen abdeckt.
emk2203
Hesekiel 25:17 - Gesegnet ist, wer im Namen der Nächstenliebe und des guten Willens diese Lösung befürwortet, denn er ist der Hüter seines Bruders und der Finder verlorener Kinder.
Jan Sila
Unintuitiv kann der Pfad nicht '.' in debian. Wenn Sie ein '.' es findet nichts.
Isaaclw
Ich frage mich, ob es wirklich funktioniert, es scheint, dass chinesische Zeichen entfernt / ersetzt werden 的节奏啊, aber diese Zeichen sind gültige Dateinamen.
11.
5

Dieses Shell-Skript bereinigt ein Verzeichnis rekursiv, um Dateien zwischen Linux / Windows und FAT / NTFS / exFAT portierbar zu machen. Es entfernt Steuerzeichen /:*?"<>\|und einige reservierte Windows-Namen wie COM0.

sanitize() {
  shopt -s extglob;

  filename=$(basename "$1")
  directory=$(dirname "$1")

  filename_clean=$(echo "$filename" | sed -e 's/[\\/:\*\?"<>\|\x01-\x1F\x7F]//g' -e 's/^\(nul\|prn\|con\|lpt[0-9]\|com[0-9]\|aux\)\(\.\|$\)//i' -e 's/^\.*$//' -e 's/^$/NONAME/')

  if (test "$filename" != "$filename_clean")
  then
    mv -v "$1" "$directory/$filename_clean"
  fi
}

export -f sanitize

sanitize_dir() {
  find "$1" -depth -exec bash -c 'sanitize "$0"' {} \;
}

sanitize_dir '/path/to/somewhere'

Linux ist theoretisch weniger restriktiv ( /und \0in Dateinamen strengstens verboten), in der Praxis stören jedoch mehrere Zeichen Bash-Befehle (wie *...), weshalb sie auch in Dateinamen vermieden werden sollten.

Gute Quellen für Einschränkungen bei der Benennung von Dateien:

KrisWebDev
quelle
1
Es was ich suche! Aber füge Anführungszeichen hinzu, um Verzeichnisse mit Leerzeichen zu unterstützen. find "$ 1" -depth -exec bash -c 'sanitize "$ 0"' {} \;
mmv-ru
1

Wenn Sie eingebettete Zeilenumbrüche, Multibyte-Zeichen, Leerzeichen, führende Bindestriche, umgekehrte Schrägstriche und Leerzeichen verarbeiten möchten, benötigen Sie etwas Robusteres. Lesen Sie dazu die Antwort:
https://superuser.com/a/858671/365691

Ich stelle das Skript bei Interesse auf code.google.com ein: rnf-bash-rename-script

A.Danischewski
quelle
Das hier verlinkte Skript hat das Problem für mich gelöst
Jeremiah Rose
0

Ich verwende diesen Einzeiler, um ungültige Zeichen in Untertiteldateien zu entfernen:

for f in *.srt; do nf=$(echo "$f" |sed -e 's/[^A-Za-z0-9.]/./g' |sed 's/\.\.\././g' |sed 's/\.\././g'); test "$f" != "$nf" && mv "$f" "$nf" && echo "$nf"; done
  1. Nur * .srt-Dateien verarbeiten (* kann anstelle von * .srt verwendet werden, um jede Datei zu verarbeiten)
  2. Entfernt alle anderen Zeichen mit Ausnahme der Buchstaben A-Za-z, der Ziffern 0-9 und der Punkte "."
  3. Entfernt mögliche Doppel- oder Dreifachperioden
  4. Überprüft, ob der Dateiname ungültige Zeichen enthält
  5. Wenn true, wird die Datei mit dem Befehl mv umbenannt und die mit dem Befehl echo vorgenommenen Änderungen ausgegeben
Brian Küpper
quelle
-2

für Datei in *; do mv "$ file" $ (echo "$ file" | sed -es / [^ A-Za-z0-9. -] / / g '); getan &

Jairo Bernal
quelle
2
Sie sollten erklären, was Ihr Code macht und die richtige Formatierung verwenden. Ihr Code kann dazu führen, dass Dateien gelöscht werden, indem Kollisionen in den Namen eingefügt werden. Und das Ganze im Hintergrund laufen zu lassen, ist irgendwie albern.
Kasperd