¿Es posible utilizar "/" en un nombre de archivo?

111

Sé que esto no es algo que deba hacerse nunca, pero ¿hay alguna manera de usar el carácter de barra que normalmente separa los directorios dentro de un nombre de archivo en Linux?

subcan
fuente
1
Supongo que puede modificar el nombre de un archivo usando acceso directo a la partición de su disco duro y parchear con un carácter '/' en alguna parte. Lo que sucede es una pregunta interesante ... lo más probable es que no sea lo que quieres.
hochl
1
Pero la respuesta corta debería ser: no, esto no es algo que deba hacerse nunca :-)
Simeon Visser
¿Hackear una barra en el nombre del archivo en la entrada del directorio en el recuento de FS? No sería recomendable; nunca podrá acceder al archivo.
Jonathan Leffler
35
Esto me recuerda la vez que mi amigo creó un archivo con un nombre *y luego preguntó: "¿Cómo elimino un archivo?" Respondí, rmseguido del nombre del archivo. Bueno, ya sabes el resto.
David Heffernan
1
Para los nuevos usuarios de Linux, cuando no está seguro acerca de una expresión o nombre de archivo, creo que es una buena práctica usar lspara enumerar los archivos que desea eliminar y luego cambiar el lscomando a rmdespués.
Dave F

Respuestas:

129

La respuesta es que no puede, a menos que su sistema de archivos tenga un error. Este es el por qué:

Hay una llamada al sistema para cambiar el nombre de su archivo definido en fs/namei.cllamado renameat:

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

Cuando se invoca la llamada al sistema, realiza una búsqueda de ruta ( do_path_lookup) en el nombre. Siga rastreando esto, y llegamos a lo link_path_walkque tiene esto:

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

Este código se aplica a cualquier sistema de archivos. ¿Que significa esto? Significa que si intenta pasar un parámetro con un '/'carácter real como nombre del archivo usando medios tradicionales, no hará lo que desea. No hay forma de escapar del personaje. Si un sistema de archivos "admite" esto, es porque:

  • Utilice un carácter Unicode o algo que parezca una barra pero no lo sea.
  • Tienen un error.

Por otra parte, si lo hizo entrar y editar los bytes añadir un carácter de barra en un nombre de archivo, las cosas malas que pasaría. Eso es porque nunca podrías referirte a este archivo por su nombre :( ya que siempre que lo hicieras, Linux supondría que te refieres a un directorio inexistente. Usar la técnica 'rm *' tampoco funcionaría, ya que bash simplemente expande eso al nombre del archivo. Incluso rm -rfno funcionaría, ya que un simple strace revela cómo van las cosas bajo el capó (abreviado):

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

Tenga en cuenta que estas llamadas a unlinkatfallarían porque necesitan hacer referencia a los archivos por su nombre.

Robert Martin
fuente
8
Además, tenga en cuenta que al menos e2fsckconsidera cualquier nombre de archivo como un nombre de archivo ilegal que debe corregirse; consulte la fuente . Entonces, si de alguna manera termina con un nombre de archivo que tiene barras, puede usarlo fsckpara solucionar el problema.
ehabkost
4
@ehabkost ¿ Algún nombre de archivo? Suena como un error en e2fsck: p
flarn2006
36

Puede usar un carácter Unicode que se muestre como "/" (por ejemplo, este glifo aparentemente redundante ) asumiendo que su sistema de archivos lo admite.

Blackle Mori
fuente
42
Sí, precisamente: solo /, que es U + 002F SOLIDUS, está prohibido. Hay muchos otros candidatos adecuados: ⁄ es U + 2044 FRACTION SLASH; ∕ es U + 2215 DIVISION SLASH; ⧸ es U + 29F8 BIG SOLIDUS; / Es U + FF0F FULLWIDTH SOLIDUSy ╱ es U + 2571 es BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT. ¡Todo funcionaría admirablemente!
tchrist
2
Pero, ¿qué pasa si el usuario usa esos caracteres reales en sus nombres de archivo / directorio? Necesitamos una solución de escape genérica. Lástima que el código normal de Linux no admite ninguno, ya que literalmente coincide con ASCII 0x2F. ASCII es un gran no-no desde hace al menos 20 años. (¡Unicode 1.0 es de 1991!)
Evi1M4chine
@tchrist prefiero no depender de Unicode. así que probablemente preferiría un delimitador de varios caracteres como ---. su elección del delimitador puede usar un carácter diferente y variar el número de repeticiones.
Trevor Boyd Smith
Para obtener una lista de posibles reemplazos en numerosos caracteres, que están prohibidos en diferentes sistemas de archivos, eche un vistazo a mi respuesta: stackoverflow.com/a/61448658/4575793
Cadoiz
9

Depende del sistema de archivos que esté utilizando. De algunos de los más populares:

Nicolas
fuente
1
no depende solo del sistema de archivos, las llamadas al sistema en todos los sistemas * nix analizarán / como un componente del árbol de directorios.
Blackle Mori
2
El carácter de barra inclinada está codificado en el kernel, independientemente del sistema de archivos (intente hacerlo grep -r "'/'" *en la fuente del kernel)
Robert Martin
20
@tchrist Disculpe. "Forward slash" es una forma completamente aceptable de referirse al carácter de barra para dejar bien claro a qué barra se refiere. A veces la gente se confunde: P
Robert Martin
2
Ja, pero @tchrist también tiene razón, creo. ¿Por qué adelante 'implica' / 'y' atrás 'implica' \ '? La mejor explicación que tengo hasta ahora es que si se escribe con un bolígrafo que comienza en una línea, de abajo hacia arriba, '/' se mueve hacia la derecha o 'adelante' y '\' se mueve 'izquierda' o 'atrás', al leer / escribir de izquierda a derecha. Sin embargo, realmente no me gusta esa explicación, en parte porque no siempre escribo mis personajes desde abajo y avanzo. Creo que comenzar desde arriba y avanzar hacia abajo mientras se escribe un personaje a menudo fluye mejor.
Jesse W. Collins
4
@jwso Esto es totalmente un punto lateral, pero es un lenguaje canónico estándar. Slash no es lo que Unicode llama símbolos que se parecen a estos, los llama solidus, pero "\" es un solidus inverso, que es sinónimo de backward, por lo tanto, backslash. Pero si uno necesita una justificación, atrás y adelante es la dirección en que la línea se inclina o debería caer, con una dirección basada en la dirección de la escritura (de izquierda a derecha). Se inclina o debería caer <== o hacia atrás si se ve como "\", y ==> o hacia adelante si se ve como "/".
Stuart R. Jefferys
4

Solo con una codificación acordada. Por ejemplo, podría aceptar que %se codificará como %%y eso %2Fsignificará un /. Todo el software que accedió a este archivo debería comprender la codificación.

David Schwartz
fuente
19
"lo que llamamos una barra con cualquier otro nombre olería tan mal" - Shakespeare
Robert Martin
1

La respuesta corta es: No, no puedes. Es una prohibición necesaria debido a cómo se define la estructura del directorio.

Y, como se mencionó, puede mostrar un carácter Unicode que "parece" una barra, pero eso es todo lo que puede llegar a tener.

keyer
fuente
1

En general, es una mala idea intentar utilizar caracteres "malos" en un nombre de archivo; incluso si lo administra de alguna manera, tiende a dificultar el uso del archivo más adelante. El separador del sistema de archivos es plano y no va a funcionar en absoluto, por lo que tendrá que elegir un método alternativo.

¿Ha considerado codificar la URL y luego usarla como nombre de archivo? El resultado debería estar bien como nombre de archivo y es fácil reconstruir el nombre a partir de la versión codificada.

Otra opción es crear un índice: cree el nombre del archivo de salida utilizando el método que desee: nombres numerados secuencialmente, hashes SHA1, lo que sea, luego escriba un archivo con el par de nombre de archivo / URL generado. Puede guardar eso en un hash y usarlo para hacer una búsqueda de URL a nombre de archivo o viceversa con la versión inversa del hash, y puede escribirlo y volver a cargarlo más tarde si es necesario.

Joe McMahon
fuente