shasum de un directorio en macos

shasum de un directorio en macos

Estoy escribiendo un script de shell que usa shasumpara verificar si el contenido de un directorio ha cambiado.

En Linux y FreeBSD, shasumtienen el mismo comportamiento cuando lo hago shasum <directory>, sin embargo, en MacOS shasumme 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

tarSería excelente ya que "archiva" una carpeta y luego podría shasumhacerlo, 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 taren 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 tarpunto de vista, todo está bien, pero debido al orden, shasumproduce un hash diferente.

CONCLUSIÓN

shasumes 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 findcomando, 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 tarpara crear un archivo temporal y luego hacer un shasumtambié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

mtreees 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 fooy 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 mtreenuevamente y pásele el manifiesto que creó anteriormente y mtreele 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

fooTambié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

información relacionada