2012-03-23 13 views
70

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 file in Linux?È possibile utilizzare "/" in un nome file?

+2

Quale file system? – Nicolas

+1

Immagino che tu possa modificare il nome di un file usando l'accesso diretto alla tua partizione hardisk e patch in un carattere '/' da qualche parte. 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 :-) –

risposta

93

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 file definito fs/namei.c chiamato renameat:

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

Quando la chiamata di sistema viene invocata, si fa una ricerca percorso (do_path_lookup) sul nome. Tieni tracciare questo, e si arriva a link_path_walk che 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? Ciò significa che se si tenta di passare un parametro con un carattere effettivo '/' come nome del file utilizzando i metodi tradizionali, non farà ciò che si desidera. Non c'è modo di sfuggire al personaggio. Se un file system "supporta" questo, è perché o:

  • utilizzare un carattere Unicode o qualcosa che sembra come una barra, ma non lo è.
  • Hanno un bug.

Inoltre, se hai entrare e modificare il byte per aggiungere un carattere barra in un nome di file, le cose cattive sarebbe accaduto. Questo perché non si può mai fare riferimento a questo file per nome :(dal momento in cui lo si è fatto, Linux assumerebbe che si stesse riferendo a una directory inesistente. L'uso della tecnica 'rm *' non avrebbe funzionato, dal momento che bash lo espande semplicemente al nome file.Anche rm -rf non avrebbe funzionato, dal momento che una semplice strace 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 unlinkat fallirebbe perché hanno bisogno di fare riferimento ai file per nome.

+4

Inoltre, si noti che almeno 'e2fsck' considera qualsiasi nome di file come un nome di file illegale che deve essere risolto- [vedere la fonte] (http://git.kernel.org/?p=fs/ ext2/e2fsprogs.git; a = blob; f = e2fsck/pass2.C# L455). Quindi, se in qualche modo finisci con un nome di file che contiene delle barre, puoi usare 'fsck' per risolvere il problema. – ehabkost

26

È possibile utilizzare un carattere Unicode che viene visualizzato come "/" (ad esempio this seemingly redundant glyph) assumendo che il proprio filesystem lo supporti.

+25

Sì, precisamente: solo /, che è U + 002F 'SOLIDUS', è vietato. Ci sono molti altri candidati adatti:/è U + 2044 'FRACTION SLASH';/È U + 2215 'DIVISION SLASH'; ⧸ è U + 29F8 'BIG SOLIDUS';/È U + FF0F 'FULLWIDTH SOLIDUS', e ╱ è U + 2571 è' BOX DISEGNI LUCE DIAGONALE SUPERIORE A DESTRA INFERIORE A SINISTRA'. Tutti lavorerebbero ammirevolmente! – tchrist

+0

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

0

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

E, come già detto, è possibile visualizzare un carattere unicode che "assomiglia" a una barra, ma questo è il massimo che si ottiene.

4

Solo con una codifica concordata. Ad esempio, è possibile convenire che % sarà codificato come %% e chesignificherà uno /. Tutto il software che ha avuto accesso a questo file dovrebbe comprendere la codifica.

+13

"quello che noi chiamiamo una barra con qualsiasi altro nome sarebbe un cattivo odore" - Shakespeare –

3

Dipende dal file system che si sta utilizzando. Di alcuni di quelli più popolari:

+1

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

+0

Il carattere di barra diretta è codificato nel kernel, indipendentemente dal file system (prova a fare 'grep -r" '/' "*' nel sorgente del tuo kernel) –

+0

@RobertMartin "Avanti" barra ??? – tchrist

1

In generale è una cattiva idea provare a utilizzare caratteri "cattivi" in un nome di file; anche se in qualche modo lo gestisci, tende a rendere difficile l'uso del file in un secondo momento. Il separatore del filesystem non funziona affatto, quindi dovrai scegliere un metodo alternativo.

Hai considerato la codifica URL dell'URL, quindi l'hai utilizzata come nome file? Il risultato dovrebbe essere corretto come nome file ed è facile ricostruire il nome dalla versione codificata.

Un'altra opzione è quella di creare un indice - creare il nome del file di output utilizzando qualsiasi metodo che ti piace - nomi in sequenza numerata, SHA1 hash, qualunque sia - quindi scrivere un file con la coppia nome/URL generato. 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 seguito, se necessario.