Ist in einem Dateinamen kein Leerzeichen zulässig?

31

Es heißt, dass Sie unter Unix und Linux generell vermeiden sollten, Leerzeichen in einem Dateinamen zu haben (normale Datei, Verzeichnis, Link, Gerätedatei, ...).

Aber das mache ich die ganze Zeit. Für einen Dateinamen mit einem Leerzeichen

  • In Nautilus wird das Leerzeichen als Leerzeichen angezeigt.
  • Im Bash-Terminal \ stelle ich entweder ein Leerzeichen dar oder setze den Dateinamen in doppelte Anführungszeichen.
  • In einigen Anwendungsdateien (Nautilus, nicht sicher, ob das Betriebssystem dies auch tut) wird der Dateiname mit dem durch ersetzten Leerzeichen geschrieben %20.

Ist ein Leerzeichen in einem Dateinamen wirklich nicht erlaubt?

Wie wird ein Leerzeichen in einem Dateinamen richtig verwendet oder behandelt?

Tim
quelle
17
Es ist erlaubt, aber es ist sehr, sehr ärgerlich. Es gibt keinen Grund dafür. Tu es nicht.
Leichtigkeit Rennen mit Monica
3
Sie können auch Dateien mit dem Namen -rf ~(use touch -- "-rf ~") erstellen , ich würde es jedoch nicht empfehlen.
Ian D. Scott
5
Sie können es tun, es ist erlaubt, wie ein Selbstzerstörungsskript namens "cd" zu erstellen, aber Sie sollten es nicht tun. Deine Datei sieht in 3 verschiedenen Tools schon anders aus, ist das nicht schlimm genug?
Falco
7
Nicht jeder teilt die Meinung, dass es wirklich, wirklich ärgerlich ist. Und "Es gibt keinen Grund dafür" ist so offensichtlich falsch, dass es keiner Widerlegung bedarf. Ich habe vor Jahren nachgegeben und gelernt, wie man mit Räumen richtig umgeht, und zum größten Teil ist es wirklich keine große Sache.
2
@snailboat Leerzeichen sind ein Symptom für das eigentliche Problem, bei dem es an Standardisierung mangelt. Mit Unix-Dateisystemen können "Dateinamen" nahezu uneingeschränkte binäre Blobs enthalten. Die einzigen unzulässigen Bytes sind 0 und 47 (das /Trennzeichen). Die Verwendung aller 254 verbleibenden Bytes öffnet die Tür zu allen Arten von unsagbaren eldritch "Namen". Offensichtlich ist das verrückt, aber nicht jeder ist sich einig, was "gesund" ist, und verschiedene Charaktere werden verschiedene Werkzeuge zerstören. Der Schnittpunkt aller Menschen ist ziemlich klein .
JW013

Antworten:

48

Leerzeichen und in der Tat alle Zeichen außer /und NUL sind in Dateinamen zulässig. Die Empfehlung, keine Leerzeichen in Dateinamen zu verwenden, beruht auf der Gefahr, dass sie von Software, die sie schlecht unterstützt, falsch interpretiert werden. Wahrscheinlich ist eine solche Software fehlerhaft. Aber auch Programmiersprachen wie Shell-Skripte machen es allzu einfach, Software zu schreiben, die bei der Darstellung von Dateinamen mit Leerzeichen abbricht. Diese Fehler treten häufig auf, weil Shell-Skripte von ihren Entwicklern nicht oft mit Dateinamen mit Leerzeichen getestet werden Sie.

Leerzeichen, die durch ersetzt werden %20, werden in Dateinamen nicht häufig verwendet. Dies wird hauptsächlich für (Web-) URLs verwendet. Obwohl es wahr ist, dass% -Verschlüsselung von URLs manchmal in Dateinamen gelangt, oft aus Versehen.

Celada
quelle
6
Es handelt sich um "URL-Codierung" oder "Prozent-Codierung". De.wikipedia.org/wiki/URL_encoding Der am besten geeignete Name ist wahrscheinlich "URI-Codierung", aber die Leute finden URL leichter auszusprechen als URI , daher ist dies eine übliche Form von Fehlbezeichnung. Beachten Sie, dass der Satz reservierter Zeichen in URIs größer ist als für * nix-Dateinamen.
Goldlöckchen
1
@ Tim Ich weiß nicht, dass Sie ein NUL-Zeichen in jedem Befehlszeilenargument in angeben könnenbash . Ich habe ein paar Dinge ausprobiert, wie das Zitieren mit Strg-V und so, $(echo -e \\0)aber es hat nicht funktioniert. Der Grund, warum NUL nicht in Dateinamen verwendet werden kann, ist, dass es nicht in C-Strings verwendet werden kann (da es sich um den String-Terminator handelt) und alle zugrunde liegenden APIs sowie praktisch alle von C-Programmen verarbeiteten Strings dieses Format verwenden . Da bashes in C geschrieben ist, hat es möglicherweise überhaupt keine Unterstützung für Zeichenfolgen, in denen NUL enthalten ist. Ich könnte mich irren, es könnte einen undurchsichtigen Weg geben ...
Celada
1
Art hängt vom Kontext ab. Zeichenfolgenfunktionen zählen im Allgemeinen nicht die endgültige Null (oder besser gesagt, die erste Null ist das Ende der Zeichenfolge, auch wenn sich etwas dahinter befindet). In diesem Sinne hat sie also die Länge Null und wird daher als leer betrachtet.
Goldlöckchen
3
@ Celada kannst du natürlich benutzen NULund bash, das brauchst du $'\0'. Zum Beispiel:find . -print0 | while read -d $'\0' f; do echo "$f"; done
terdon
1
@goldilocks Sprechen die Leute URL tatsächlich als 'url' aus und reimen sich ungefähr mit 'earl'?
Miles Rout
17

Leerzeichen sind in Dateinamen erlaubt, wie Sie gesehen haben.

Wenn Sie sich den Eintrag "Die meisten UNIX-Dateisysteme" in diesem Diagramm in Wikipedia ansehen , werden Sie feststellen:

  • Jeder 8-Bit-Zeichensatz ist zulässig. Wir können unter diesem Dach auch 7-Bit-ASCII subsumieren, da es sich um eine Teilmenge verschiedener 8-Bit-Mengen handelt und immer mit 8-Bit-Bytes implementiert wird.

  • Die einzigen verbotenen Zeichen sind /und "null". "Null" bezieht sich auf ein Null-Byte, diese sind jedoch in Textdaten ohnehin nicht zulässig.

Allerdings , wenn Sie keine Nutzung der Schale machen, merkt man kann, dass es einige Zeichen, die einen stress schaffen, was am wichtigsten *, die ein POSIX Globbing Operator ist.

Je nachdem , wie Sie wollen „Ärger“ definieren, Sie könnten umfassen Leerzeichen (Leerzeichen, Tabulatoren, Zeilenumbrüche usw.) gibt, da dies die Notwendigkeit schafft mit für zitiert "". Aber das ist unvermeidlich, da Leerzeichen erlaubt sind, also ...

Wie wird ein Leerzeichen in einem Dateinamen richtig verwendet oder behandelt?

Schließen Sie in einem Shell- / Befehlszeilenkontext den Dateinamen in einfache oder doppelte Anführungszeichen (beachten Sie jedoch, dass dies nicht dasselbe WRT-Problem ist wie in anderen Fällen) oder schließen Sie die Leerzeichen mit den folgenden \Zeichen ab:

> foo my\ file\ with\ spaces\ in\ the\ name
Goldlöckchen
quelle
1
Wie spezifizierst du das NUL Zeichen in der Bash? Ich möchte es in einem Dateinamen testen.
Tim
1
Das kannst du nicht. Die "Ausführungssemantik" bezieht sich auf die Tatsache, dass in C (und jeder anderen mir bekannten Sprache) Textzeichenfolgen mit Nullen abgeschlossen sind. Die Shell ist in C implementiert. Das Schlimmste, was ich mir vorstellen kann, ist touch $(echo -e "foo\00bar")- -eProzesse \0Nals Oktalwert, aber sie gehen trotzdem irgendwo verloren, da nur eine Datei namens erstellt wird foobar. Natürlich kann NULL nicht gedruckt werden, aber ich garantiere, dass es aufgrund der C-String-Einschränkung von dort weg ist.
Goldlöckchen
"text strings are null terminated" -> Zur weiteren Erläuterung: Strings werden immer mit einem Null-Byte am Ende gespeichert, weshalb es im Text "nicht erlaubt" ist: Wenn Sie einen einfügen, haben Sie den String effektiv terminiert an diesem Punkt. ZB foo[NULL]barwürde wie foofür die meisten Absichten und Zwecke enden . Die Tatsache, dass dies nicht der Fall ist, echo -ezeigt , dass der NULL-Wert irgendwo gestrichen wurde.
Goldlöckchen
5
In den meisten Programmiersprachen sind Nullzeichen in Zeichenfolgen zulässig. Es kommt nur vor, dass die Hauptsprache, auf der Unix basiert, nicht C ist - und die meisten Unix-Shells erlauben auch keine Null-Zeichen in Strings. In jedem Fall, @Tim, verwenden alle Unix-Schnittstellen nullterminierte Strings, sodass ein Null-Byte das einzige ist, was Sie in einem Dateinamen niemals haben können (plus /ist das Verzeichnistrennzeichen und kann nicht in Anführungszeichen gesetzt werden, kann also in einem Pfadnamen stehen) aber nicht in einem Dateinamen).
Gilles 'SO - hör auf böse zu sein'
1
... aber [schon wieder egal]. Das würde ich sowieso nicht zu oft tun. Meiner Meinung nach gibt es keinen Grund für sie, in Textdaten zu sein. Ich hätte das korrigiert, aber es ist ein Kommentar.
Goldlöckchen
3

Der Grund ist größtenteils historischer Natur. Damals waren Leerzeichen in Dateinamen nicht zulässig, daher wurden Leerzeichen als Trennzeichen zwischen Schlüsselwörtern und Dateinamen verwendet. Zukünftige Shell-Interpreter mussten mit alten Skripten kompatibel sein, und daher stecken wir bei den heutigen Kopfschmerzen fest.

Entwickler von Prozessen, die sich nicht sehr mit Menschen auseinandersetzen müssen, können die Dinge sehr viel einfacher machen, indem sie Leerzeichen ganz weglassen. Apple tut dies, der Inhalt von / System / Library / CoreServices / enthält sehr wenige Leerzeichen, die Programme mit Leerzeichen werden im Auftrag des Benutzers geöffnet und WouldLookStrangeIfCamelCased. Ähnliche Nur-Unix-Pfade vermeiden auch Leerzeichen.

(etwas verwandte Anekdote: Mitte der 90er Jahre sagte eine Windows-Drohne: "Nennen Sie eine Sache, die Sie auf einem Mac tun können, die ich unter Windows nicht kann" -> "Verwenden Sie 12 Zeichen in einem Dateinamen." -> Stille. Leerzeichen waren auch in diesen 12 Zeichen möglich)

paul
quelle
1
Ich habe früher V6 Unix (um 1978) verwendet. Leerzeichen waren damals erlaubt. Eine Aufgabe, die ich hatte, war, ein Programm zu schreiben, um das Dateisystem (unter Verwendung von Direct Disk I / O) zu analysieren und nach einer Datei zu suchen, deren Name Leerzeichen und Leerzeichen enthielt.
Wallyk
Löschen sie Leerzeichen insgesamt - oder enthalten die Dateinamen nur sehr wenige Leerzeichen?
Mikeserv
2

Also ja, wie oft an anderer Stelle angegeben, kann ein Dateiname fast jedes Zeichen enthalten. Aber es muss gesagt werden , dass ein Dateiname ist nicht eine Datei. Es hat einiges Gewicht als Datei trägt Attribut , dass Sie in der Regel einen Dateinamen müssen öffnen eine Datei, sondern eine Name der Datei nur verweist auf die eigentliche Datei. Hierbei handelt es sich um eine Verknüpfung, die in dem Verzeichnis gespeichert ist, in dem sie gespeichert wurde, zusammen mit der Inode-Nummer - eine viel engere Annäherung an eine tatsächliche Datei .

Nennen Sie es also, wie Sie wollen. Der Kernel kümmert sich nicht darum - alle Dateireferenzen, die er verarbeiten wird, werden sowieso mit realen Inode-Nummern umgehen. Der Dateiname ist eine Sache für den menschlichen Verzehr - wenn Sie es zu einer verrückten Sache machen wollen, dann ist es Ihr Dateisystem. Hier mache ich ein paar verrückte Sachen:

Zuerst erstelle ich 20 Dateien und benenne sie mit Leerzeichen. Jeder Dateiname enthält ein Leerzeichen mehr als der letzte:

until [ $((i=$i+1)) -gt 20 ]
do  v=$v' ' && touch ./"$v"
done

Das ist irgendwie lustig. Schau dir meine an ls:

ls -d ./*
./      ./          ./              ./                  ./                 
./      ./          ./              ./                  ./                  
./      ./          ./              ./                  ./                   
./      ./          ./              ./                  ./     

Jetzt werde ich dieses Verzeichnis spiegeln:

set -- * ; mkdir ../mirror
ls -i1qdU -- "$@" |
sh -c 'while read inum na
    do  ln -T "$1" ../mirror/$inum
    shift ; done' -- "$@"
ls -d ../mirror/*

Hier sind ../mirror/die Inhalte:

../mirror/423759  ../mirror/423764  ../mirror/423769  ../mirror/423774
../mirror/423760  ../mirror/423765  ../mirror/423770  ../mirror/423775
../mirror/423761  ../mirror/423766  ../mirror/423771  ../mirror/423776
../mirror/423762  ../mirror/423767  ../mirror/423772  ../mirror/423777
../mirror/423763  ../mirror/423768  ../mirror/423773  ../mirror/423778

Ok, aber vielleicht fragst du - aber was nützt das? Woran erkennt man was was ist? Wie können Sie sogar sicher sein, dass Sie die richtige Inode-Nummer mit dem richtigen Dateinamen verknüpft haben?

Gut...

echo "heyhey" >>./'    ' 
tgt=$(ls -id ./'    ')
cat ../mirror/${tgt%% .*} \
    $(ls -1td ../mirror/* | head -n1) 

AUSGABE

heyhey
heyhey

Siehe, sowohl die in enthaltene ../mirror/"${tgt%% .*}"als auch die mit referenzierte Inode-Nummer ./' 'beziehen sich auf dieselbe Datei. Sie beschreiben die gleiche Datei. Sie nennen es, aber nichts weiter. Eigentlich gibt es kein Rätsel, nur einige Unannehmlichkeiten, die Sie sich möglicherweise selbst machen, die sich aber letztendlich kaum oder gar nicht auf den Betrieb Ihres Unix-Dateisystems auswirken werden.

mikeserv
quelle