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 hará el truco:
$ 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 mezclen, 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 reemplazado find -s
con una llamada a sort
. El -k 2
bit le dice que omita el hash MD5, por lo que solo clasifica los nombres de archivo, que están en el campo 2 hasta el final de la línea, según sort
el cálculo.
Hay una debilidad con esta versión del comando, que es probable que se confunda si tiene nombres de archivo con nuevas líneas en ellos, porque parecerá que hay varias líneas en la sort
llamada. La find -s
variante no tiene ese problema, porque el recorrido y la clasificación del árbol 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 se dé cuenta de esto al usar ls
y tal, que silenciosamente ordena el contenido del directorio por usted. find
sin -s
o una sort
llamada imprimirá los archivos en cualquier orden que el sistema de archivos subyacente los devuelva, lo que hará que este comando dé un valor hash modificado si el orden de los archivos que se le da como entrada cambia.
Es posible que deba cambiar los md5sum
comandos 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
comando en consecuencia. Otra trampa es que algunos programas de suma de datos no escriben un nombre de archivo, un buen ejemplo es el antiguo sum
programa de Unix .
Este método es algo ineficiente, llamando a md5sum
N + 1 veces, donde N es el número 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 algo en un árbol ha cambiado, no solo el contenido del archivo, solicite tar
empacar el contenido del directorio y envíelo a md5sum
:
$ tar -cf - somedir | md5sum
Debido a que tar
también ve permisos de archivos, 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 el find
método basado anteriormente, 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 te encuentras con falsos positivos, te recomiendo ir con la find | cpio
opción en la respuesta de Gilles .
find .
lugar defind somedir
. De esta forma, los nombres de los archivos son los mismos cuando se proporcionan diferentes especificaciones de ruta para buscar; esto puede ser complicado :-)