Wie behandelt Linux mehrere aufeinanderfolgende Pfadtrennzeichen (/ home //// Benutzername /// Datei)?

111

Ich arbeite an einem Python-Skript, das Dateispeicherorte an einen SCP-Unterprozess übergibt. Das ist alles in Ordnung, aber ich bin in einer Situation, in der ich möglicherweise einen Pfad mit einem Dateinamen verketten muss, sodass /der Pfad ein Doppel 'enthält . Ich weiß, dass es Bash egal ist, ob Sie mehrere Dateitrennzeichen haben, aber ich frage mich, wie genau das korrigiert wird. Ist es Bash, das extra /s auszieht, oder spielt es wirklich keine Rolle?

Ich frage, weil es mir mehrere Codezeilen erspart, um /beim Verketten nach zusätzlichen s zu suchen. Ich weiß, dass es keine große Sache ist, aber ich bin auch neugierig. Ich habe ein Bash-Skript mit der Zeile cd //usr(anstelle von cd /usr), was darauf hindeutet, dass die Verwendung mehrerer /s in einem Pfad möglicherweise von Bedeutung ist

Falmarri
quelle
7
Ich würde in die zusätzlichen Codezeilen investieren ...
Stefan
5
Für den Fall , jemand kümmert, die ich bin sicher , dass niemand tut, ich in der Tat mit dem Python am Ende joinund abspathund solche Befehle.
Falmarri

Antworten:

165

Es sind mehrere Schrägstriche zulässig, die einem einzelnen Schrägstrich entsprechen. Aus der Single Unix-Spezifikation (Version 3) , Basisdefinitionen §3.266 Pfadname : "Mehrere aufeinanderfolgende Schrägstriche werden als ein Schrägstrich gleichgesetzt."

Es gibt eine Ausnahme: Wenn ein Pfadname mit genau zwei Schrägstrichen beginnt, kann er unterschiedlich behandelt werden ( siehe Basisdefinitionen §4.11 Auflösung von Pfadnamen ). Linux selbst tut dies nicht, obwohl einige Anwendungen und andere Unix-Systeme dies tun (zB Cygwin).

Ein Abschluß /am Ende eines Pfadnamens zwingt den Pfadnamen, auf ein Verzeichnis zu verweisen. In ( POSIX 1003,1-2.001 (Single Unix v3) Basisdefinitionen §4.11 Pfadname Auflösung , eine Hinter /ist äquivalent zu einer Hinter /.. POSIX 1003,1-2.008 (Single Unix v4) Basisdefinitionen §4.12 die Anforderung es äquivalent zu machen , entfernt /., um mit nicht existierenden Verzeichnissen fertig zu werden (zB mkdir foo/muss funktionieren, mkdir foo/.würde aber nicht - die Gründe für die Änderung sehen).

Wenn es sich bei Programmen, die auf einen Verzeichniseintrag angewendet werden, fooum eine symbolische Verknüpfung zu einem Verzeichnis handelt, können Sie durch Übergeben foo/festlegen, dass das Programm auf das Verzeichnis und nicht auf die symbolische Verknüpfung angewendet wird.

¹ Beachten Sie, dass dies nur für die Pfadnamenauflösung gilt, dh beim Zugriff auf Dateien. Manipulationen an Dateinamen funktionieren möglicherweise anders. Zum Beispiel basenameund dirnameignoriere abschließende Schrägstriche.

Gilles
quelle
7
Das Äquivalent zu /.wurde nach einem späteren Diskussionsprozess entfernt, da es nicht eindeutig war. Wie auch immer, +1, da es schwierig ist, diese Art von Informationen gut zusammengefasst zu finden.
Hakre
17

Das Betriebssystem scheint sich auch nicht darum zu kümmern, da es gerade ein C-Programm mit einem direkten Systemaufruf ausprobiert hat, um es mit einem // im Pfad zu öffnen.

Sie können die Python-Bibliotheksfunktion os.path.normpath verwenden, um sie jedoch zu normalisieren, sodass Sie die Zeichenfolge nicht mehr nach Extras durchsuchen müssen. Andere Sprachen haben ähnliche Funktionen.

http://docs.python.org/library/os.path.html#os.path.normpath

Ivatar
quelle
5
Beachten Sie den folgenden Kommentar in der Quelle von normpath: Normalisieren Sie einen Pfad, z. B. A // B, A /./ B und A / foo /../ B werden alle zu A / B. Es versteht sich, dass dies die Bedeutung des Pfades ändern kann, wenn er symbolische Verknüpfungen enthält!
Bluehorn
8

Auf allen Unix-Systemen, die ich gesehen habe, ist es dasselbe wie ein einzelnes /, aber der Unix-Standard gibt das an

Ein Pfadname, der mit zwei aufeinanderfolgenden Schrägstrichen beginnt, kann implementierungsdefiniert interpretiert werden, obwohl mehr als zwei führende Schrägstriche als ein einzelner Schrägstrich behandelt werden sollen.

Abhängig von Ihrem System kann es daher speziell gehandhabt werden. (Einige ältere Unix-Versionen verwendeten einen doppelten Zeilenabstand /für den Fernzugriff auf das Dateisystem, und möglicherweise gibt es noch einige, die dies tun.)

Fred Foo
quelle
7
Cygwin (obwohl kein richtiger UNIX) übersetzt //remote/...in den Remote-Dateisystemzugriff, wahrscheinlich aus Gründen der Konsistenz mit Windows \\remote\....
ephemient
2
Ich glaube, dass Windows POSIX-kompatible APIs //remote/...das gleiche wie das UNC- Pfadformat behandeln (kann aber derzeit keine gute Referenz googeln) \\remote\....
Stephen P
1
Ich denke, ich erinnere mich, dass die portablen Pfadnamen von Boost.Filesystem auf //besondere Weise behandelt werden, indem sie möglicherweise falseauf Absolutheit getestet werden und der Unix / POSIX-Spezifikation entsprechen.
7

Verwenden Sie os.path.joinin Python und Sie erhalten nicht mehrere Schrägstriche. Das Erstellen von Dateinamen durch Verketten von Zeichenfolgen wird als schlechter Python-Stil angesehen.

Neil Mayhew
quelle
Ich stimme zu, aber der Dateiname ist Teil einer Befehlszeichenfolge, und anstatt die Befehlszeichenfolge zum Anhängen an den Dateinamen (am Ende) zu analysieren, möchte ich sie nur anhängen.
Falmarri
1
@ Falmarri: Sie können nicht einfach einen Dateinamen an eine Befehlszeichenfolge anhängen! Eine Befehlszeichenfolge wird von der Shell analysiert, daher müssen Sonderzeichen in Dateinamen in Anführungszeichen gesetzt werden. Sie müssen also den Dateinamen erstellen und ihn in Anführungszeichen setzen, um ihn in die Befehlszeichenfolge einzufügen.
Gilles
Dies ist ein wirklich spezifisches Projekt, das ich so ziemlich nur selbst verwenden werde. Ich war mir wahrscheinlich nicht klar genug, um zu rechtfertigen, dass ich in dieser Hinsicht nicht robust bin. Ich erhalte diese Dateipfadzeichenfolge von einer Klasse, die mir einen korrekt maskierten Dateipfad usw. gibt. Und ich
hänge
1
@ Falmarri: Verwenden Sie also normpath, um den Befehlszeilenwert, den Sie nicht steuern, zu bereinigen, und verwenden Sie anschließend join, um sie zusammenzusetzen.
Neil Mayhew
Dies ist eigentlich das, was ich letztendlich getan habe = \ Ich konnte den speziellen Fall, in dem ich gerade /sehr gut behandelt wurde, nicht bewältigen .
Falmarri,
3

Es gibt keinen Unterschied.

Mehrere Schrägstriche werden ignoriert (ohne Wirkung), zB:

ls -al //usr///////bin/sed
ChristopheD
quelle
7
Es kann sein, wenn es genau zwei sind und am Anfang; Ein Pfadname, der mit zwei aufeinanderfolgenden Schrägstrichen beginnt, kann implementierungsdefiniert interpretiert werden . In der Praxis halte ich das für richtig und sie werden einfach ignoriert
Michael Mrozek
Danke Chris, ich freue mich über die Klarstellung! (Leider funktioniert der OpenID-Login nicht für mich oder ich würde dich abstimmen)
@Rob Sie sind nicht registriert, aber immer noch angemeldet (Ihr Cookie verfolgt Sie). Sie sollten sich jetzt registrieren können, um eine OpenID mit Ihrem Konto zu verbinden, aber Sie sollten so oder so abstimmen können
Michael Mrozek
Danke Michael aber "du musst dich einloggen oder registrieren um abzustimmen". Wenn Sie nur eine E-Mail-Adresse und einen Namen verwenden, haben Sie nicht alle Rechte. Und da OpenID ausläuft und ich keine Lust habe, ein neues Konto zu erstellen, habe ich Pech. Ich glaube, ich bin schuld daran, dass ich faul bin, aber ich weiß die Hilfe zu schätzen.
0

Natürlich können Sie einen Pfad mit möglichen Mehrfach / (Schrägstrichen) normalisieren, indem Sie ihn durchlaufen tr -s

NORMALIZED=$(echo "$UNHYGIENIC" | tr -s / /)

... und dann benutzen $NORMALIZED

Es sollte jedoch notwendig sein. Soweit mir bekannt ist, sollte jeder UNIX-Kernel Trennzeichen für gleichzeitige Pfade ignorieren - oder sie konzeptionell als ... /./... behandeln.

Jim Dennis
quelle
"sollte" -> "sollte nicht".