È possibile utilizzare "/" in un nome di file?


111

So che questo non è qualcosa che dovrebbe mai essere fatto, ma c'è un modo per usare il carattere barra che normalmente separa le directory all'interno di un nome di file in Linux?


1
Immagino che tu possa modificare il nome di un file utilizzando l'accesso diretto alla partizione del disco rigido e applicare da qualche parte un carattere "/". Quello che succede è una domanda interessante ... molto probabilmente non è quello che vuoi.
hochl

1
Ma la risposta breve dovrebbe essere: no, questo non è qualcosa che dovrebbe mai essere fatto :-)
Simeon Visser

L'hacking di una barra nel nome del file nella voce della directory in FS conta? Non sarebbe consigliato; non saresti in grado di accedere al file, mai.
Jonathan Leffler

35
Questo mi ricorda la volta in cui il mio amico ha creato un file denominato *e poi ha chiesto: "Come faccio a rimuovere un file?" Ho risposto, rmseguito dal nome del file. Bene, sai il resto.
David Heffernan

1
Per i nuovi utenti Linux, quando non sei sicuro di un'espressione o di un nome di file, penso che sia buona pratica usare lsper elencare i file che vuoi rimuovere e poi cambiare il lscomando in rmseguito.
Dave F

Risposte:


129

La risposta è che non puoi, a meno che il tuo filesystem non abbia un bug. Ecco perché:

C'è una chiamata di sistema per rinominare il tuo file definito in fs/namei.cchiamato renameat:

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

Quando la chiamata di sistema viene invocata, esegue una ricerca del percorso ( do_path_lookup) sul nome. Continua a rintracciarlo e arriviamo a quello link_path_walkche ha questo:

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

Questo codice si applica a qualsiasi file system. Cosa significa questo? Significa che se provi a passare un parametro con un '/'carattere reale come nome del file usando i mezzi tradizionali, non farà quello che vuoi. Non c'è modo di sfuggire al personaggio. Se un filesystem "supporta" questo, è perché:

  • Usa un carattere Unicode o qualcosa che assomigli a una barra ma non lo è.
  • Hanno un bug.

Inoltre, se si ha fatto entrare e modificare i byte per aggiungere un carattere barra in un nome di file, le cose cattive sarebbe accaduto. Questo perché non potresti mai fare riferimento a questo file per nome :( poiché ogni volta che lo fai, Linux presume che ti riferisci a una directory inesistente. Anche l'uso della tecnica 'rm *' non funzionerebbe, poiché bash lo espande semplicemente al nome del file. Nemmeno rm -rffunzionerebbe, dal momento che una semplice stringa rivela come vanno le cose sotto il cofano (abbreviato):

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

Si noti che queste chiamate a unlinkatfallirebbero perché devono fare riferimento ai file per nome.


8
Inoltre, nota che e2fsckconsidera almeno qualsiasi nome di file come un nome di file illegale che deve essere corretto - vedi la fonte . Quindi, se in qualche modo ti ritrovi con un nome di file che contiene delle barre, puoi usarlo fsckper risolvere il problema.
ehabkost

4
@ehabkost Qualche nome di file? Sembra un bug in e2fsck: p
flarn2006

36

Potresti usare un carattere Unicode che viene visualizzato come "/" (ad esempio questo glifo apparentemente ridondante ) supponendo che il tuo filesystem lo supporti.


42
Sì, precisamente: solo /, che è U + 002F SOLIDUS, è vietato. Ci sono molti altri candidati idonei: ⁄ è U + 2044 FRACTION SLASH; ∕ è U + 2215 DIVISION SLASH; ⧸ è U + 29F8 BIG SOLIDUS; / È U + FF0F FULLWIDTH SOLIDUSe ╱ è U + 2571 è BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT. Tutto funzionerebbe egregiamente!
tchrist

2
Ma allora cosa succede se l'utente usa quei caratteri effettivi nei suoi nomi di file / directory? Abbiamo bisogno di una soluzione generica di fuga. Peccato che il normale codice di Linux non ne supporti nessuno, poiché corrisponde letteralmente a ASCII 0x2F. ASCII è un grande no-no da almeno 20 anni. (Unicode 1.0 è del 1991!)
Evi1M4chine

@tchrist preferisco non dipendere da Unicode. quindi probabilmente preferirei un delimitatore multi-carattere come ---. la scelta del delimetro può utilizzare un carattere diverso e variare il numero di ripetizioni.
Trevor Boyd Smith

Per un elenco dei possibili sostituti su numerosi personaggi, che sono vietati in diversi file system, dare un'occhiata alla mia risposta: stackoverflow.com/a/61448658/4575793
Cadoiz

9

Dipende dal filesystem che stai usando. Di alcuni dei più popolari:


1
non dipende solo dal file system, le chiamate di sistema in tutti i sistemi * nix analizzeranno / come un componente dell'albero delle directory.
Blackle Mori

2
Il carattere barra è codificato nel kernel, indipendentemente dal file system (prova a farlo grep -r "'/'" *nel sorgente del kernel)
Robert Martin

20
@tchrist Mi scusi. "Barra in avanti" è un modo completamente accettabile di riferirsi al carattere barra per rendere completamente chiaro a quale barra ci si riferisce. A volte le persone si confondono: P
Robert Martin

2
Hah, ma anche @tchrist ha ragione, credo. Perché forward "implica" / "e" back "implica" \ "? La migliore spiegazione che ho finora è che se scritto con una penna che inizia su una riga, dal basso verso l'alto, "/" si sposta a destra o "avanti" e "\" si sposta a "sinistra" o "indietro" durante la lettura / scrittura da sinistra a destra. Non mi piace molto questa spiegazione, in parte perché non scrivo sempre i miei personaggi dal basso e vado verso l'alto. Penso che partire dall'alto e scendere mentre si scrive un personaggio spesso scorre meglio.
Jesse W. Collins,

4
@jwso Questo è totalmente un punto laterale, ma questo è un linguaggio standard e canonico. Slash non è ciò che Unicode chiama simboli che assomigliano a questi, li chiama solidus, ma "\" è un solidus inverso, che è sinonimo di backwards, quindi backslash. Ma se è necessaria una giustificazione, avanti e indietro sono la direzione in cui la linea si inclina o dovrebbe cadere, con direzione basata sulla direzione della scrittura (da sinistra a destra). Si inclina o dovrebbe cadere <== o all'indietro se ha l'aspetto di "\" e ==> o in avanti se ha l'aspetto di "/".
Stuart R. Jefferys

4

Solo con una codifica concordata. Ad esempio, potresti concordare che %verrà codificato come %%e che %2Fsignificherà un /. Tutto il software che ha avuto accesso a questo file dovrebbe comprendere la codifica.


19
"ciò che chiamiamo taglio con qualsiasi altro nome avrebbe un odore altrettanto disgustoso" - Shakespeare
Robert Martin

1

La risposta breve è: no, non puoi. È un divieto necessario a causa di come è definita la struttura della directory.

E, come accennato, puoi visualizzare un carattere Unicode che "assomiglia" a una barra, ma questo è quanto puoi ottenere.


1

In generale è una cattiva idea provare a usare caratteri "cattivi" in un nome di file; anche se in qualche modo lo gestisci, tende a rendere difficile l'utilizzo del file in seguito. Il separatore del file system non funzionerà affatto, quindi dovrai scegliere un metodo alternativo.

Hai preso in considerazione la codifica URL dell'URL, quindi utilizzarlo come nome del file? Il risultato dovrebbe andare bene come nome di file ed è facile ricostruire il nome dalla versione codificata.

Un'altra opzione è creare un indice: creare il nome del file di output usando il metodo che preferisci - nomi numerati in sequenza, hash SHA1, qualunque cosa - quindi scrivere un file con la coppia nome file / URL generata. Puoi salvarlo in un hash e usarlo per eseguire una ricerca da URL a nome file o viceversa con la versione invertita dell'hash, e puoi scriverlo e ricaricarlo in un secondo momento, se necessario.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.