Cree un archivo tar sobre la marcha y canalícelo a md5sum
:
tar c dir | md5sum
Esto produce un único valor hash MD5 que debe ser único para la configuración de su archivo y subdirectorio. No se crean archivos en el disco.
Si solo te preocupan los archivos y no los directorios vacíos, esto funciona bien:
find /path -type f | sort -u | xargs cat | md5sum
sugerencia de ire_and_curses de usar tar c <dir>
tiene algunos problemas:
- tar procesa las entradas del directorio en el orden en que se almacenan en el sistema de archivos y no hay forma de cambiar este orden. Esto efectivamente puede generar resultados completamente diferentes si tiene el "mismo" directorio en diferentes lugares, y no sé cómo solucionarlo (tar no puede "ordenar" sus archivos de entrada en un orden particular).
- Por lo general, me importa si los números de ID de grupo e ID de propietario son iguales, no necesariamente si la representación de cadena de grupo/propietario es la misma. Esto está en línea con lo que, por ejemplo,
rsync -a --delete
lo hace:sincroniza prácticamente todo (menos xattrs y acls), pero sincronizará el propietario y el grupo en función de su ID, no en la representación de cadenas. Entonces, si se sincronizó con un sistema diferente que no necesariamente tiene los mismos usuarios/grupos, debe agregar el--numeric-owner
bandera a alquitrán - tar incluirá el nombre de archivo del directorio que está revisando, solo algo que debe tener en cuenta.
Mientras no haya una solución para el primer problema (o a menos que esté seguro de que no le afecta), no usaría este enfoque.
El find
propuesto Las soluciones basadas en software tampoco son buenas porque solo incluyen archivos, no directorios, lo que se convierte en un problema si la suma de verificación debe tener en cuenta los directorios vacíos.
Finalmente, la mayoría de las soluciones sugeridas no se ordenan de manera consistente, porque la intercalación puede ser diferente entre los sistemas.
Esta es la solución que se me ocurrió:
dir=<mydir>; (find "$dir" -type f -exec md5sum {} +; find "$dir" -type d) | LC_ALL=C sort | md5sum
Notas sobre esta solución:
- El
LC_ALL=C
es garantizar un orden de clasificación fiable en todos los sistemas - Esto no diferencia entre un directorio "nombrado\nconunanuevalínea" y dos directorios "nombrado" y "conunanuevalínea", pero la posibilidad de que eso ocurra parece muy poco probable. Normalmente se soluciona esto con un
-print0
bandera parafind
, pero como hay otras cosas sucediendo aquí, solo puedo ver soluciones que harían que el comando fuera más complicado de lo que vale.
PD:uno de mis sistemas usa un busybox limitado find
que no es compatible con -exec
ni -print0
banderas, y también agrega '/' para indicar directorios, mientras que findutils find no parece hacerlo, así que para esta máquina necesito ejecutar:
dir=<mydir>; (find "$dir" -type f | while read f; do md5sum "$f"; done; find "$dir" -type d | sed 's#/$##') | LC_ALL=C sort | md5sum
Afortunadamente, no tengo archivos/directorios con líneas nuevas en sus nombres, así que esto no es un problema en ese sistema.
find /path/to/dir/ -type f -name "*.py" -exec md5sum {} + | awk '{print $1}' | sort | md5sum
El encontrar El comando enumera todos los archivos que terminan en .py. El valor hash MD5 se calcula para cada archivo .py. AWK se usa para seleccionar los valores hash MD5 (ignorando los nombres de archivo, que pueden no ser únicos). Los valores hash MD5 están ordenados. Luego se devuelve el valor hash MD5 de esta lista ordenada.
He probado esto copiando un directorio de prueba:
rsync -a ~/pybin/ ~/pybin2/
Cambié el nombre de algunos de los archivos en ~/pybin2 .
El find...md5sum
El comando devuelve el mismo resultado para ambos directorios.
2bcf49a4d19ef9abd284311108d626f1 -
Para tener en cuenta el diseño del archivo (rutas), de modo que la suma de comprobación cambie si se cambia el nombre o se mueve un archivo, el comando se puede simplificar:
find /path/to/dir/ -type f -name "*.py" -exec md5sum {} + | md5sum
En macOS con md5
:
find /path/to/dir/ -type f -name "*.py" -exec md5 {} + | md5