El programa md5sum no proporciona sumas de verificación para directorios. Quiero obtener una sola suma de verificación MD5 para todo el contenido de un directorio, incluidos los archivos en los subdirectorios. Es decir, una suma de comprobación combinada formada por todos los archivos. ¿Hay alguna manera de hacer esto?
Respuesta aceptada:
La forma correcta depende exactamente de por qué estás preguntando:
Opción 1:Comparar solo datos
Si solo necesita un hash del contenido del archivo del árbol, esto será suficiente:
$ find -s somedir -type f -exec md5sum {} ; | md5sum
Esto primero resume todo el contenido del archivo individualmente, en un orden predecible, luego pasa esa lista de nombres de archivo y hash MD5 para que se convierta en hash, dando un valor único que solo cambia cuando cambia el contenido de uno de los archivos en el árbol.
Desafortunadamente, find -s
solo funciona con BSD find(1), utilizado en macOS, FreeBSD, NetBSD y OpenBSD. Para obtener algo comparable en un sistema con GNU o SUS find(1), necesita algo un poco más feo:
$ find somedir -type f -exec md5sum {} ; | sort -k 2 | md5sum
Hemos imitado el comportamiento de BSD find -s
agregando una llamada a sort
. El -k 2
bit le dice que omita el hash MD5, por lo que solo ordena los nombres de los archivos, que están en el campo 2 hasta el final de la línea por sort
está calculando.
Hay una debilidad con esta versión del comando, que es probable que se confunda si tiene algún nombre de archivo con líneas nuevas en ellos, porque se verá como varias líneas en el sort
llamar. El find -s
variant no tiene ese problema, porque el recorrido del árbol y la clasificación ocurren dentro del mismo programa, find
.
En cualquier caso, la clasificación es necesaria para evitar falsos positivos:los sistemas de archivos Unix/Linux más comunes no mantienen las listas de directorios en un orden estable y predecible. Es posible que no te des cuenta de esto al usar ls
y demás, que clasifican silenciosamente el contenido del directorio por usted. Llamando a find
sin ordenar su salida de alguna manera hará que el orden de las líneas en la salida coincida con el orden que el sistema de archivos subyacente les devuelva, lo que hará que este comando proporcione un valor hash modificado si cambia el orden de los archivos que se le dan como entrada, incluso si los datos siguen siendo idénticos.
Bien puede preguntarse si el -k 2
bit en el GNU sort
el comando anterior es necesario. Dado que el hash de los datos del archivo es un proxy adecuado para el nombre del archivo siempre que el contenido no haya cambiado, no obtendremos falsos positivos si descartamos esta opción, lo que nos permite usar el mismo comando tanto con GNU como con BSD sort
. Sin embargo, tenga en cuenta que existe una pequeña posibilidad (1:2 con MD5) de que el orden exacto de los nombres de los archivos no coincida con el orden parcial sin -k 2
puede dar si alguna vez hay una colisión hash. Sin embargo, tenga en cuenta que si las posibilidades tan pequeñas de una discrepancia son importantes para su aplicación, es probable que todo este enfoque esté fuera de su alcance.
Es posible que deba cambiar el md5sum
comandos a md5
o alguna otra función hash. Si elige otra función hash y necesita la segunda forma del comando para su sistema, es posible que deba ajustar el sort
manda en consecuencia. Otra trampa es que algunos programas de suma de datos no escriben un nombre de archivo en absoluto, un buen ejemplo es el antiguo Unix sum
programa.
Este método es algo ineficiente, llamando a md5sum
N+1 veces, donde N es la cantidad de archivos en el árbol, pero ese es un costo necesario para evitar el hash de metadatos de archivos y directorios.
Opción 2:comparar datos y Metadatos
Si necesita poder detectar que cualquier cosa en un árbol ha cambiado, no solo el contenido del archivo, pregunte a tar
para empaquetar el contenido del directorio por usted, luego envíelo a md5sum
:
$ tar -cf - somedir | md5sum
Porque tar
también ve permisos de archivo, propiedad, etc., esto también detectará cambios en esas cosas, no solo cambios en el contenido del archivo.
Este método es considerablemente más rápido, ya que solo hace una pasada sobre el árbol y ejecuta el programa hash solo una vez.
Al igual que con find
método basado arriba, tar
va a procesar los nombres de los archivos en el orden en que los devuelve el sistema de archivos subyacente. Bien puede ser que en su aplicación, puede estar seguro de que no hará que esto suceda. Puedo pensar en al menos tres patrones de uso diferentes donde es probable que ese sea el caso. (No voy a enumerarlos, porque estamos entrando en un territorio de comportamiento no especificado. Cada sistema de archivos puede ser diferente aquí, incluso de una versión del sistema operativo a la siguiente).
Si encuentra que obtiene falsos positivos, le recomiendo ir con find | cpio
opción en la respuesta de Gilles.