Estoy escribiendo un script de shell que usa shasum
para verificar si el contenido de un directorio ha cambiado.
En Linux y FreeBSD, shasum
tienen el mismo comportamiento cuando lo hago shasum <directory>
, sin embargo, en MacOS shasum
me dan hashes.solo para archivos.
FreeBSD
$ shasum CONTENTS/
7f986e5e5289c59db1bba48df92ffe4707830aaa CONTENTS/
linux
$ shasum CONTENTS/
7f986e5e5289c59db1bba48df92ffe4707830aaa CONTENTS/
Mac OS
$ shasum CONTENTS/
shasum: CONTENTS/:
¿Cómo podría calcular el hash de un directorio en MacOS?
PRUEBA 1: Usar TAR con tuberías
Intenté usarlo pero parece que esta opción tar no funciona en MacOS.
tar cO CONTENTS/ | shasum
tar: Option -O is not permitted in mode -c
da39a3ee5e6b4b0d3255bfef95601890afd80709 -
INTENTO 2: Usar FIND/EXEC
Era consistente entre MacOS y FreeBSD, pero Linux devolvió un hash extraño
find CONTENTS -type f -exec shasum {} \; | sort -k 2 | shasum
linux
c2ddb9bc5f543e956f5cdcc76750cb78cc5f26f3
FreeBSD
3ac2a9d4e2fc5d2d2ec3c7f612e680990cc35824
Mac OS
3ac2a9d4e2fc5d2d2ec3c7f612e680990cc35824
OTROS HALLAZGOS SOBRE EL ALQUITRÁN
tar
Sería excelente ya que "archiva" una carpeta y luego podría shasum
hacerlo, sin embargo, el orden de cómo tar
"recorrer" la estructura de carpetas esno consistente entre sistemas operativos. Como algunos ayudantes mencionaron en los comentarios, debería usar la misma versión tar
en todos los sistemas.
Solo un ejemplo, en el sistema 1 tengo este orden:
drwxr-xr-x 0 root wheel 0 27 Jul 07:23 usr/
-rw-r--r-- 0 root wheel 0 27 Jul 07:25 usr/aaa
drwxr-xr-x 0 root wheel 0 27 Jul 07:25 usr/f1/
-rw-r--r-- 0 root wheel 0 27 Jul 07:25 usr/f1/aaa
drwxr-xr-x 0 root wheel 0 27 Jul 07:25 usr/f1/f0/
-rw-r--r-- 0 root wheel 0 27 Jul 07:25 usr/f1/f0/aaa
drwxr-xr-x 0 root wheel 0 27 Jul 07:25 usr/f2/
-rw-r--r-- 0 root wheel 0 27 Jul 07:25 usr/f2/aaa
drwxr-xr-x 0 root wheel 0 27 Jul 07:25 usr/f2/f1/
-rw-r--r-- 0 root wheel 0 27 Jul 07:25 usr/f2/f1/aaa
drwxr-xr-x 0 root wheel 0 27 Jul 07:25 usr/f2/f1/f0/
-rw-r--r-- 0 root wheel 0 27 Jul 07:25 usr/f2/f1/f0/aaa
drwxr-xr-x 0 root wheel 0 27 Jul 07:25 usr/f3/
-rw-r--r-- 0 root wheel 0 27 Jul 07:25 usr/f3/aaa
drwxr-xr-x 0 root wheel 0 27 Jul 07:25 usr/f3/f2/
-rw-r--r-- 0 root wheel 0 27 Jul 07:25 usr/f3/f2/aaa
drwxr-xr-x 0 root wheel 0 27 Jul 07:25 usr/f3/f2/f1/
-rw-r--r-- 0 root wheel 0 27 Jul 07:25 usr/f3/f2/f1/aaa
y en el sistema 2 tengo el siguiente orden:
drwxr-xr-x 0 root wheel 0 27 Jul 07:23 usr/
-rw-r--r-- 0 root wheel 0 27 Jul 07:25 usr/aaa
drwxr-xr-x 0 root wheel 0 27 Jul 07:25 usr/f1/
drwxr-xr-x 0 root wheel 0 27 Jul 07:25 usr/f2/
drwxr-xr-x 0 root wheel 0 27 Jul 07:25 usr/f3/
-rw-r--r-- 0 root wheel 0 27 Jul 07:25 usr/f3/aaa
drwxr-xr-x 0 root wheel 0 27 Jul 07:25 usr/f3/f2/
-rw-r--r-- 0 root wheel 0 27 Jul 07:25 usr/f3/f2/aaa
drwxr-xr-x 0 root wheel 0 27 Jul 07:25 usr/f3/f2/f1/
-rw-r--r-- 0 root wheel 0 27 Jul 07:25 usr/f3/f2/f1/aaa
-rw-r--r-- 0 root wheel 0 27 Jul 07:25 usr/f2/aaa
drwxr-xr-x 0 root wheel 0 27 Jul 07:25 usr/f2/f1/
-rw-r--r-- 0 root wheel 0 27 Jul 07:25 usr/f2/f1/aaa
drwxr-xr-x 0 root wheel 0 27 Jul 07:25 usr/f2/f1/f0/
-rw-r--r-- 0 root wheel 0 27 Jul 07:25 usr/f2/f1/f0/aaa
-rw-r--r-- 0 root wheel 0 27 Jul 07:25 usr/f1/aaa
drwxr-xr-x 0 root wheel 0 27 Jul 07:25 usr/f1/f0/
-rw-r--r-- 0 root wheel 0 27 Jul 07:25 usr/f1/f0/aaa
Desde un tar
punto de vista, todo está bien, pero debido al orden, shasum
produce un hash diferente.
CONCLUSIÓN
shasum
es consistente entre Linux y BSD para verificar el hash de un archivo individual, pero, cuando se trata de directorios, la coherencia ocurre solo en MacOS y FreeBSD, tal vez debido a cómo se ordenan los archivos.
Si se aplica la clasificación mediante el find
comando, la coherencia solo se obtiene en FreeBSD y MacOS; sin embargo, este método consume mucho tiempo, ya que lleva una cantidad significativa de tiempo calcular los hashes para cada archivo y luego el hash de toda la estructura.
Usar tar
para crear un archivo temporal y luego hacer un shasum
también resultó ser inconsistente entre Linux y BSD, tal vez debido a la diferencia en el método de archivo.
Creo que el único camino a seguir esrediseñar mi solución.
Respuesta1
mtree
es la herramienta que deseas.
Suponer:
$ mkdir foo
$ date > foo/date1; sleep 3
$ date > foo/date2; sleep 3
$ date > foo/date3
$ grep . foo/*
foo/date1:Wed Jul 24 16:11:32 PDT 2019
foo/date2:Wed Jul 24 16:11:35 PDT 2019
foo/date3:Wed Jul 24 16:11:38 PDT 2019
$ find . -ls
7318841 0 drwxr-xr-x 3 admin staff 102 Jul 24 16:11 .
7318847 0 drwxr-xr-x 5 admin staff 170 Jul 24 16:11 ./foo
7318849 8 -rw-r--r-- 1 admin staff 29 Jul 24 16:11 ./foo/date1
7318851 8 -rw-r--r-- 1 admin staff 29 Jul 24 16:11 ./foo/date2
7318853 8 -rw-r--r-- 1 admin staff 29 Jul 24 16:11 ./foo/date3
Cree un manifiesto de referencia del directorio foo
y guárdelo en foo.mtree
:
$ mtree -c -K sha256digest -p foo > foo.mtree
Ahora ve y juega con cualquier archivo en ese directorio.
$ touch foo/date3
Ejecute mtree
nuevamente y pásele el manifiesto que creó anteriormente y mtree
le indicará qué cambió:
$ mtree -p foo < foo.mtree || echo fail
date3 changed
modification time expected Wed Jul 24 16:11:38 2019 found Wed Jul 24 16:14:00 2019
fail
$ echo '$ date > foo/date2' >> bar
$ mtree -p foo < foo.mtree || echo fail
date2 changed
modification time expected Wed Jul 24 16:11:35 2019 found Wed Jul 24 16:19:40 2019
SHA-256 expected c76a568f08d98c2830f2fdfb42415c3ec15341b8741450d4bbd863f1d5c4c691 found ddcf8d07785bfe4d031a989339835dc3b8b44653019568dcee612c44fc8e2f70
date3 changed
modification time expected Wed Jul 24 16:11:38 2019 found Wed Jul 24 16:14:00 2019
fail
foo
También se informará sobre cualquier archivo que falte o se haya agregado desde que se creó el manifiesto:
$ mv foo/date1 foo/date4
$ mtree -p foo < foo.mtree || echo fail
. changed
modification time expected Wed Jul 24 16:11:38 2019 found Wed Jul 24 16:21:38 2019
date2 changed
modification time expected Wed Jul 24 16:11:35 2019 found Wed Jul 24 16:19:40 2019
SHA-256 expected c76a568f08d98c2830f2fdfb42415c3ec15341b8741450d4bbd863f1d5c4c691 found ddcf8d07785bfe4d031a989339835dc3b8b44653019568dcee612c44fc8e2f70
date3 changed
modification time expected Wed Jul 24 16:11:38 2019 found Wed Jul 24 16:14:00 2019
date4 extra
./date1 missing
fail
Respuesta2
RmlintHará lo que (creo que es) quieras.
Puntos relevantes:
- No utiliza SHA de forma predeterminada, pero se le puede indicar que lo haga.
- Se puede instalar en MacOS mediante homebrew.
- De forma predeterminada, no calcula una suma de comprobación para un único directorio especificado. Se le puede indicar que calcule sumas de verificación para todos los directorios desde un punto de partida determinado, como una forma de encontrar directorios "duplicados" debajo de ese punto. Pero como efecto secundario, también hará exactamente lo que parece estar pidiendo.
- Puede que sea excesivo para lo que está buscando y puede que le lleve un tiempo descubrir las mejores opciones para usar, pero es bastante sólido.
- Averiguar qué indicadores usar puede resultar complicado. Obtener sumas de verificación de directorio es bastante fácil, pero hacerlonohacer otras cosas, puede ser complicado. (Aunque, para ser claros, en realidad no modifica nada. A lo sumo, genera un script de shell, que puedes ejecutar manualmente más tarde, para modificar cosas si lo deseas. Lo que parece que necesitas es la salida JSON y/o CSV archivos, que le darán la suma de comprobación del directorio que está buscando).
Utilizo rmlint en un script bash para buscar directorios duplicados. Aquí hay un comando que hará como mínimo lo que usted desea y lo menos posible:
rmlint "base/dir/to/start/from" --see-symlinks --hidden --algorithm=sha256 --types=none,duplicatedirs --no-backup -o csv:log.csv