md5sum antepone '\' a la suma de comprobación

22

¿Por qué md5sum está anteponiendo "\" delante de la suma de comprobación cuando se encuentra la suma de comprobación de un archivo con "\" en el nombre?

$ md5sum /tmp/test\\test
\d41d8cd98f00b204e9800998ecf8427e  /tmp/test\\test

Lo mismo se observa para cualquier otra utilidad.

jsaji
fuente
Solo como referencia, las otras *sumutilidades (de la misma familia que md5sum, e, g, sha1sumetc.) en GNU coreutils hacen lo mismo.
Kusalananda
No veo este comportamiento, ¿cuál es la versión de la utilidad:md5sum --version
Kiwy
@Kusalananda Esto puede ser específico de la versión coreutils; en CentOS 7 cksumno lo hace; por ejemplo% cksum test\\test 3915528286 4 test\test
Stephen Harris
@StephenHarris Eso probablemente se deba a que cksumes una utilidad POSIX y sus especificaciones. no lo permite
Kusalananda

Respuestas:

33

Esto está documentado , para Coreutils ' md5sum:

Si el archivo contiene una barra diagonal inversa o una nueva línea, la línea se inicia con una barra diagonal inversa, y cada carácter problemático en el nombre del archivo se escapa con una barra diagonal inversa, lo que hace que la salida sea inequívoca incluso en presencia de nombres de archivo arbitrarios.

( archivo es el nombre del archivo, no el contenido del archivo).

b2sum, sha1sumY los diversos SHA-2 herramientas se comportan de la misma manera que md5sum. sumy cksumno lo hagas; sumsólo se proporciona para compatibilidad hacia atrás (y sus antepasados no producen salida citado), y cksumse especifican por POSIX y no permite que este tipo de salida.

Este comportamiento se introdujo en noviembre de 2015 y se lanzó en la versión 8.25 (enero de 2016), con la siguiente NEWSentrada:

md5sumahora asegura una sola línea por archivo para el estado en la salida estándar, usando un '\' al comienzo de la línea y reemplazando cualquier nueva línea con '\ n'. Esto también afecta sha1sum, sha224sum, sha256sum, sha384sumy sha512sum.

La barra invertida al comienzo de la línea sirve como un indicador: los escapes en los nombres de archivo solo se procesan si la línea comienza con una barra invertida. (El desempañamiento no puede ser el comportamiento predeterminado: rompería las sumas generadas con versiones anteriores de Coreutils que contienen \\o \nen los nombres de archivo almacenados).

Stephen Kitt
fuente
30
Sin manembargo, es una pena que algo completamente intuitivo como este no esté documentado en las páginas. (Y sí, estoy consciente de que GNU quiere que todos lean sus infopáginas altamente enrevesadas )
Roaima
3
@msouth la barra invertida al comienzo de la línea sirve como una bandera que indica que las barras invertidas en el nombre del archivo son escapes; de lo contrario no sabría si procesar, \netc., como literales o escapes.
Stephen Kitt
3
@msouth si está al comienzo del nombre del archivo, no tienes forma de saber si es la bandera o un nombre de archivo que realmente comienza con una barra invertida ...
Stephen Kitt
1
@StephenKitt No creo que la \ principal esté ahí para la desambiguación. No hay ambigüedad si la salida se documenta como siempre escapando de barras diagonales inversas y líneas nuevas. Está ahí para que no tenga que escapar si no es necesario. Por supuesto, puede debatir si esto vale la pena (personalmente creo que no lo es, pero no soy un coreutilscontribuyente).
TypeIA
1
La frase de la documentación "cada carácter problemático en el nombre del archivo se escapa con una barra diagonal inversa" es incorrecta; ¡reemplazar una nueva línea con \nno es lo mismo que escapar de una nueva línea con una barra invertida!
ruakh
17

La respuesta de Stephen Kitt cubre el qué y trataré de cubrir por qué se implementó este cambio. Primero, alguien observó que un nombre de archivo que contenga nuevas líneas 1 podría generar un resultado ambiguo . Por ejemplo, considere esta salida:

d41d8cd98f00b204e9800998ecf8427e  foo
25af89c92254a806b2e93fffd8ac1814  bar

¿Significa esto que había dos archivos fooy bar, o solo un archivo cuyo nombre de archivo es "foo\n25af89c92254a806b2e93fffd8ac1814 bar"? De acuerdo, esta última posibilidad es altamente improbable, pero es posible. Para resolver la ambigüedad, los desarrolladores optaron por escapar de las nuevas líneas con una barra diagonal inversa ( \). La salida se vuelve distinguible. Sin embargo, entonces hay otra ambigüedad:

764efa883dda1e11db47671c4a3bbd9e  foo\nbar

¿El nombre de este archivo contiene una nueva línea o una barra invertida seguida de un n? Para resolver esto, también necesitamos escapar de las barras invertidas, de modo que el último caso se convierta en:

764efa883dda1e11db47671c4a3bbd9e  foo\\nbar

Finalmente, eligieron anteponer cada línea de salida que contiene dichos escapes con un \\para facilitar el analizador detecte si se ha escapado. Presumiblemente, esto se hizo para permitir que los analizadores manejen la salida tanto de versiones de escape como de versiones md5sumsin escape (no GNU). La bandera también significa que no es necesario hacer un escape "costoso" cuando no es necesario. Puede ver un ejemplo de este análisis en acción en md5sum.csí mismo (línea 382 en la versión vinculada).


1 Por nueva línea me refiero al carácter \nque a veces también se conoce específicamente como salto de línea o LF ; vermd5sum.c .

TypeIA
fuente
1
Por supuesto, el comportamiento sensato sería prohibir completamente todos los archivos que contengan una nueva línea. Solo rehúsate a procesarlos.
tubería
1
@pipe es un comportamiento loco . POSIX permite dichos nombres de archivo, y las utilidades que se niegan intencionalmente a trabajar con archivos legítimos son malas y deben ser eliminadas con fuego.
Ruslan
2
@Ruslan El objetivo es protestar contra POSIX por permitir tales nombres antisociales . Permitir que tales caracteres probablemente haya causado una gran cantidad de problemas de seguridad e hinchazón de código solo para manejar tales casos especiales.
tubería
@pipe mientras LF en un nombre de archivo es de hecho antisocial, otras cosas mencionadas en su enlace son mucho más discutibles, como espacios, letras no latinas, etc.
Ruslan
Sobre ingeniería clásica por ingenieros. Lección (una vez más): no permita que los ingenieros manejen los requisitos. Encontrarán el caso más oscuro y complicado y lo elevarán al caso dominante y confundirán a todos.