Ist es möglich, "/" in einem Dateinamen zu verwenden?

111

Ich weiß, dass dies niemals getan werden sollte, aber gibt es eine Möglichkeit, den Schrägstrich zu verwenden, der normalerweise Verzeichnisse innerhalb eines Dateinamens unter Linux trennt?

Subcan
quelle
1
Ich denke, Sie können den Namen einer Datei ändern, indem Sie direkt auf Ihre Festplattenpartition zugreifen und irgendwo ein '/' Zeichen patchen. Was passiert, ist eine interessante Frage ... höchstwahrscheinlich nicht das, was Sie wollen.
hochl
1
Aber die kurze Antwort sollte lauten: Nein, das sollte man nie tun :-)
Simeon Visser
Zählt das Hacken eines Schrägstrichs in den Dateinamen im Verzeichniseintrag im FS? Es würde nicht empfohlen werden; Sie könnten niemals auf die Datei zugreifen.
Jonathan Leffler
35
Dies erinnert mich an die Zeit, als mein Freund eine Datei mit dem Namen erstellt *und dann gefragt hat: "Wie entferne ich eine Datei?" Ich antwortete, rmgefolgt vom Dateinamen. Nun, du kennst den Rest.
David Heffernan
1
Für neue Linux-Benutzer, bei denen Sie sich über einen Ausdruck oder Dateinamen nicht sicher sind, empfiehlt es sich ls, die zu entfernenden Dateien aufzulisten und anschließend den lsBefehl in " rmdanach" zu ändern .
Dave F

Antworten:

129

Die Antwort ist, dass Sie nicht können, es sei denn, Ihr Dateisystem hat einen Fehler. Hier ist der Grund:

Es gibt einen Systemaufruf zum Umbenennen Ihrer Datei mit dem fs/namei.cNamen renameat:

SYSCALL_DEFINE4(renameat, int, olddfd, const char __user *, oldname,
                int, newdfd, const char __user *, newname)

Wenn der Systemaufruf aufgerufen wird, führt er eine Pfadsuche ( do_path_lookup) für den Namen durch. Verfolgen Sie dies weiter, und wir kommen zu link_path_walkdem , was dies hat:

static int link_path_walk(const char *name, struct nameidata *nd)
{
       struct path next;
       int err;
       unsigned int lookup_flags = nd->flags;

       while (*name=='/')
              name++;
       if (!*name)
              return 0;
...

Dieser Code gilt für jedes Dateisystem. Was bedeutet das? Wenn Sie versuchen, einen Parameter mit einem tatsächlichen '/'Zeichen als Dateinamen mit herkömmlichen Mitteln zu übergeben, wird dies nicht das tun, was Sie wollen. Es gibt keine Möglichkeit, dem Charakter zu entkommen. Wenn ein Dateisystem dies "unterstützt", liegt dies daran, dass entweder:

  • Verwenden Sie ein Unicode-Zeichen oder etwas, das wie ein Schrägstrich aussieht, es aber nicht ist.
  • Sie haben einen Fehler.

Wenn Sie darüber hinaus haben die Bytes in und bearbeiten gehen , um einen Schrägstrich in einen Dateinamen hinzufügen, würden schlimme Dinge passieren. Das liegt daran, dass Sie diese Datei niemals mit Namen referenzieren könnten :( Da Linux dies immer tat, ging es davon aus, dass Sie auf ein nicht vorhandenes Verzeichnis verweisen. Die Verwendung der 'rm *' - Technik würde auch nicht funktionieren, da bash dies einfach auf den Dateinamen erweitert. Auch rm -rfwürde nicht funktionieren, da eine einfache Klammer zeigt, wie es unter der Haube weitergeht (verkürzt):

$ ls testdir
myfile2 out
$ strace -vf rm -rf testdir
...
unlinkat(3, "myfile2", 0)               = 0
unlinkat(3, "out", 0)                   = 0
fcntl(3, F_GETFD)                       = 0x1 (flags FD_CLOEXEC)
close(3)                                = 0
unlinkat(AT_FDCWD, "testdir", AT_REMOVEDIR) = 0
...

Beachten Sie, dass diese Aufrufe von unlinkatfehlschlagen würden, da sie nach Namen auf die Dateien verweisen müssen.

Robert Martin
quelle
8
Beachten Sie außerdem, dass zumindest e2fsckjeder Dateiname als unzulässiger Dateiname betrachtet wird, der behoben werden muss - siehe Quelle . Wenn Sie also irgendwie einen Dateinamen haben, der Schrägstriche enthält, können Sie fsckdas Problem beheben.
Ehabkost
4
@ehabkost Irgendein Dateiname? Klingt nach einem Fehler in e2fsck: p
flarn2006
36

Sie können ein Unicode-Zeichen verwenden, das als "/" angezeigt wird (z. B. dieses scheinbar redundante Symbol ), sofern Ihr Dateisystem dies unterstützt.

Blackle Mori
quelle
42
Ja, genau: Nur /, das U + 002F ist SOLIDUS, ist verboten. Es gibt viele andere geeignete Kandidaten: ⁄ ist U + 2044 FRACTION SLASH; ∕ ist U + 2215 DIVISION SLASH; ⧸ ist U + 29F8 BIG SOLIDUS; / Ist U + FF0F FULLWIDTH SOLIDUSund ╱ ist U + 2571 ist BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT. Alles würde bewundernswert funktionieren!
Tchrist
2
Aber was ist, wenn der Benutzer diese tatsächlichen Zeichen in seinen Datei- / Verzeichnisnamen verwendet? Wir brauchen eine generische Fluchtlösung. Schade, dass der normale Linux-Code keinen unterstützt, da er buchstäblich mit ASCII 0x2F übereinstimmt. ASCII ist seit mindestens 20 Jahren ein großes No-No. (Unicode 1.0 ist von 1991!)
Evi1M4chine
@tchrist Ich bevorzuge es, nicht von Unicode abhängig zu sein. Daher würde ich wahrscheinlich ein Trennzeichen mit mehreren Zeichen bevorzugen ---. Ihre Delimeterauswahl kann ein anderes Zeichen verwenden und die Anzahl der Wiederholungen variieren.
Trevor Boyd Smith
Eine Liste möglicher Ersetzungen für zahlreiche Zeichen, die unter verschiedenen Dateisystemen verboten sind, finden Sie in meiner Antwort: stackoverflow.com/a/61448658/4575793
Cadoiz
9

Dies hängt davon ab, welches Dateisystem Sie verwenden. Von einigen der beliebtesten:

Nicolas
quelle
1
Es hängt nicht nur vom Dateisystem ab, Systemaufrufe in allen * nix-Systemen analysieren das / als Komponente des Verzeichnisbaums.
Blackle Mori
2
Das Schrägstrichzeichen ist unabhängig vom Dateisystem fest grep -r "'/'" *im Kernel codiert (versuchen Sie es in Ihrer Kernelquelle)
Robert Martin
20
@ tchrist Entschuldigung. "Schrägstrich vorwärts" ist eine völlig akzeptable Art, sich auf das Schrägstrichzeichen zu beziehen, um gründlich zu verdeutlichen, auf welchen Schrägstrich man sich bezieht. Manchmal werden die Leute verwirrt: P
Robert Martin
2
Hah, aber @tchrist hat auch einen Punkt, denke ich. Warum bedeutet "vorwärts" / "und" zurück "" \ "? Die beste Erklärung, die ich bisher habe, ist, dass, wenn mit einem Stift geschrieben wird, der in einer Zeile von unten nach oben beginnt, sich '/' beim Lesen / Schreiben nach rechts oder 'vorwärts' und '\' nach links 'oder' zurück 'bewegt von links nach rechts. Diese Erklärung gefällt mir allerdings nicht wirklich, auch weil ich meine Charaktere nicht immer von unten schreibe und nach oben gehe. Ich denke, von oben zu beginnen und sich beim Schreiben eines Charakters nach unten zu bewegen, fließt oft besser.
Jesse W. Collins
4
@jwso Dies ist ein Nebeneffekt, aber dies ist eine kanonische Standardsprache. Schrägstrich ist nicht das, was Unicode Symbole nennt, die so aussehen, es nennt sie Solidus, aber "\" ist ein umgekehrter Solidus, der gleichbedeutend ist mit Rückwärts, also Backslash. Wenn man jedoch eine Begründung benötigt, ist Vorwärts und Rückwärts die Richtung, in die sich die Linie neigt oder fallen sollte, wobei die Richtung auf der Schreibrichtung basiert (von links nach rechts). Es neigt sich oder sollte <== oder rückwärts fallen, wenn es wie "\" aussieht, und ==> oder vorwärts, wenn es wie "/" aussieht.
Stuart R. Jefferys
4

Nur mit einer vereinbarten Kodierung. Zum Beispiel könnten Sie zustimmen, %dass codiert wird als %%und das %2Fbedeutet a /. Die gesamte Software, die auf diese Datei zugegriffen hat, muss die Codierung verstehen.

David Schwartz
quelle
19
"Das, was wir einen Schrägstrich mit einem anderen Namen nennen, würde als übel riechen" - Shakespeare
Robert Martin
1

Die kurze Antwort lautet: Nein, das kannst du nicht. Dies ist aufgrund der Definition der Verzeichnisstruktur ein notwendiges Verbot.

Und wie bereits erwähnt, können Sie ein Unicode-Zeichen anzeigen, das wie ein Schrägstrich "aussieht", aber das ist so weit wie möglich.

Keyser
quelle
1

Im Allgemeinen ist es eine schlechte Idee, überhaupt zu versuchen, "schlechte" Zeichen in einem Dateinamen zu verwenden. Selbst wenn Sie es irgendwie verwalten, ist es schwierig, die Datei später zu verwenden. Das Dateisystemtrennzeichen funktioniert auf jeden Fall überhaupt nicht, daher müssen Sie eine alternative Methode auswählen.

Haben Sie darüber nachgedacht, die URL per URL zu codieren und diese dann als Dateinamen zu verwenden? Das Ergebnis sollte als Dateiname in Ordnung sein, und es ist einfach, den Namen aus der codierten Version zu rekonstruieren.

Eine andere Möglichkeit besteht darin, einen Index zu erstellen - den Ausgabedateinamen mit einer beliebigen Methode zu erstellen - fortlaufend nummerierte Namen, SHA1-Hashes usw. - und dann eine Datei mit dem generierten Dateinamen / URL-Paar zu schreiben. Sie können dies in einem Hash speichern und damit eine URL-zu-Dateinamen-Suche durchführen oder umgekehrt mit der umgekehrten Version des Hashs. Sie können ihn ausschreiben und später bei Bedarf neu laden.

Joe McMahon
quelle