Czy można użyć „/” w nazwie pliku?

111

Wiem, że nigdy nie powinno się tego robić, ale czy istnieje sposób na użycie ukośnika, który normalnie oddziela katalogi w nazwie pliku w systemie Linux?

subcan
źródło
1
Domyślam się, że możesz zmodyfikować nazwę pliku, używając bezpośredniego dostępu do partycji dysku twardego i załatać gdzieś znak „/”. To, co się dzieje, to interesujące pytanie ... prawdopodobnie nie to, czego chcesz.
hochl
1
Ale krótka odpowiedź powinna brzmieć: nie, to nie jest coś, co powinno być kiedykolwiek zrobione :-)
Simeon Visser
Czy włamanie ukośnika do nazwy pliku we wpisie katalogu w FS liczy się? Nie byłoby to zalecane; nigdy nie będziesz mógł uzyskać dostępu do pliku.
Jonathan Leffler
35
Przypomina mi to, jak mój znajomy utworzył plik o nazwie, *a następnie zapytał: „Jak usunąć plik?” Odpowiedziałem, rma następnie nazwa pliku. Cóż, znasz resztę.
David Heffernan
1
Dla nowych użytkowników Linuksa, gdy nie masz pewności co do wyrażenia lub nazwy pliku, myślę, że dobrą praktyką jest skorzystanie lsz listy plików, które chcesz usunąć, a następnie zmiana lspolecenia na rmpóźniej.
Dave F

Odpowiedzi:

129

Odpowiedź brzmi, że nie możesz, chyba że twój system plików ma błąd. Dlatego:

Jest to wywołanie systemowe dla zmiany nazwy pliku zdefiniowanego w fs/namei.cnazywa renameat:

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

Kiedy wywołanie systemowe zostaje wywołane, wyszukuje ścieżkę ( do_path_lookup) w nazwie. Śledź to, a dojdziemy do link_path_walktego:

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;
...

Ten kod ma zastosowanie do dowolnego systemu plików. Co to znaczy? Oznacza to, że jeśli spróbujesz przekazać parametr z rzeczywistym '/'znakiem jako nazwę pliku przy użyciu tradycyjnych środków, nie zrobi on tego, co chcesz. Nie ma sposobu na ucieczkę od postaci. Jeśli system plików „obsługuje” to, dzieje się tak dlatego, że:

  • Użyj znaku Unicode lub czegoś, co wygląda jak ukośnik, ale nim nie jest.
  • Mają błąd.

Ponadto, jeśli nie iść i edytować bajtów dodać znak ukośnik w nazwie pliku, złe rzeczy się stanie. To dlatego, że nigdy nie możesz odwołać się do tego pliku po nazwie :( ponieważ kiedykolwiek to zrobiłeś, Linux założyłby, że odnosisz się do nieistniejącego katalogu. Używanie techniki „rm *” również nie zadziała, ponieważ bash po prostu rozszerza to do nazwy pliku. Nawet rm -rfby nie zadziałało, ponieważ prosty pasek pokazuje, jak się dzieje pod maską (skrócony):

$ 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
...

Zauważ, że te wywołania unlinkatzakończyłyby się niepowodzeniem, ponieważ muszą odnosić się do plików według nazwy.

Robert Martin
źródło
8
Zauważ też, że przynajmniej e2fscktraktuje każdą nazwę pliku jako niedozwoloną nazwę, którą należy naprawić - zobacz źródło . Jeśli więc w jakiś sposób otrzymasz nazwę pliku zawierającą ukośniki, możesz użyć fsckdo rozwiązania problemu.
ehabkost
4
@ehabkost Dowolna nazwa pliku? Brzmi jak błąd w e2fsck: p
flarn2006
36

Możesz użyć znaku Unicode wyświetlanego jako „/” (na przykład ten pozornie zbędny glif ), zakładając, że twój system plików go obsługuje.

Blackle Mori
źródło
43
Tak, dokładnie: tylko /, czyli U + 002F SOLIDUS, jest zabronione. Istnieje wiele innych odpowiednich kandydatów: ⁄ to U + 2044 FRACTION SLASH; ∕ wynosi U + 2215 DIVISION SLASH; ⧸ to U + 29F8 BIG SOLIDUS; / To U + FF0F FULLWIDTH SOLIDUS, a ╱ to U + 2571 to BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT. Wszystko działałoby wspaniale!
tchrist
2
Ale co wtedy, jeśli użytkownik użyje tych rzeczywistych znaków w swoich nazwach plików / katalogów? Potrzebujemy ogólnego rozwiązania ucieczki. Szkoda, że ​​normalny kod Linuksa nie obsługuje żadnego, ponieważ dosłownie pasuje do ASCII 0x2F. ASCII to wielkie nie-nie od co najmniej 20 lat. (Unicode 1.0 pochodzi z 1991 roku!)
Evi1M4chine,
@tchrist wolę nie polegać na Unicode. więc prawdopodobnie wolałbym ogranicznik wieloznakowy, taki jak ---. Twój wybór separatora może używać innego znaku i zmieniać liczbę powtórzeń.
Trevor Boyd Smith
Aby zobaczyć listę możliwych zamian wielu znaków, które są zabronione w różnych systemach plików, spójrz na moją odpowiedź: stackoverflow.com/a/61448658/4575793
Cadoiz
9

To zależy od używanego systemu plików. Niektóre z bardziej popularnych:

Nicolas
źródło
1
nie zależy tylko od systemu plików, wywołania systemowe we wszystkich systemach * nix przeanalizują / jako składnik drzewa katalogów.
Blackle Mori
2
Znak ukośnika w przód jest na stałe zakodowany w jądrze, niezależnie od systemu plików (spróbuj zrobić to grep -r "'/'" *w źródle jądra)
Robert Martin
20
@tchrist Przepraszam. „Ukośnik w przód” jest całkowicie akceptowalnym sposobem odniesienia się do znaku ukośnika, aby dokładnie wyjaśnić, do którego ukośnika się odnosi. Czasami ludzie są zdezorientowani: P
Robert Martin
2
Hah, ale myślę, że @tchrist też ma rację. Dlaczego „do przodu” oznacza „/” i „wstecz” oznacza „\”? Najlepszym wyjaśnieniem, jakie mam do tej pory, jest to, że jeśli piszę piórem zaczynając od linii, od dołu do góry, „/” przesuwa się w prawo lub „do przodu”, a „\” przesuwa się „w lewo” lub „wstecz” podczas czytania / pisania od lewej do prawej. Nie podoba mi się to wyjaśnienie, po części dlatego, że nie zawsze piszę swoje postacie od dołu i przesuwam się w górę. Myślę, że rozpoczynanie od góry i schodzenie w dół podczas pisania postaci często płynie lepiej.
Jesse W. Collins
4
@jwso To jest całkowicie poboczny punkt, ale jest to standardowy, kanoniczny język. Ukośnik nie jest tym, co Unicode nazywa symbolami wyglądającymi jak te, nazywa je solidus, ale "\" jest odwróconym solidusem, co jest synonimem odwrotnego ukośnika, stąd odwrotny ukośnik. Ale jeśli potrzebne jest uzasadnienie, wstecz i do przodu to kierunek, w którym linia pochyla się lub powinna opadać, z kierunkiem opartym na kierunku pisania (od lewej do prawej). Przechyla się lub powinien spaść <== lub do tyłu, jeśli wygląda jak „\”, i ==> lub do przodu, jeśli wygląda jak „/”.
Stuart R. Jefferys
4

Tylko z uzgodnionym kodowaniem. Na przykład możesz zgodzić się, że %zostanie zakodowany jako, %%a to %2Fbędzie oznaczać plik /. Całe oprogramowanie, które uzyskało dostęp do tego pliku, musiało rozumieć kodowanie.

David Schwartz
źródło
19
„to, co nazywamy ukośnikiem pod jakąkolwiek inną nazwą, śmierdziałoby tak obrzydliwie” - Szekspir
Robert Martin
1

Krótka odpowiedź brzmi: nie, nie możesz. Jest to konieczny zakaz ze względu na sposób zdefiniowania struktury katalogów.

Jak już wspomniano, możesz wyświetlić znak Unicode, który „wygląda jak” ukośnik, ale to tak daleko, jak to możliwe.

klucze
źródło
1

Ogólnie rzecz biorąc, w ogóle złym pomysłem jest używanie „złych” znaków w nazwie pliku; nawet jeśli w jakiś sposób nim zarządzasz, może to utrudniać późniejsze korzystanie z pliku. Separator systemu plików w ogóle nie zadziała, więc będziesz musiał wybrać alternatywną metodę.

Czy rozważałeś zakodowanie adresu URL, a następnie użycie go jako nazwy pliku? Wynik powinien być prawidłowy jako nazwa pliku, a nazwę można łatwo odtworzyć na podstawie zakodowanej wersji.

Inną opcją jest utworzenie indeksu - utwórz nazwę pliku wyjściowego przy użyciu dowolnej metody - nazwy numerowane sekwencyjnie, skróty SHA1, cokolwiek - a następnie napisz plik z wygenerowaną parą nazwa pliku / adres URL. Możesz zapisać to w hashu i użyć go do wyszukania adresu URL do nazwy pliku lub odwrotnie z odwróconą wersją skrótu, a także możesz go zapisać i ponownie załadować później, jeśli zajdzie taka potrzeba.

Joe McMahon
źródło