shasum de um diretório no macos

shasum de um diretório no macos

Estou escrevendo um script de shell que usa shasumpara verificar se o conteúdo de um diretório foi alterado.

No Linux e no FreeBSD, eles shasumtêm o mesmo comportamento quando eu o faço shasum <directory>, no entanto, no MacOS, eles shasumme fornecem hashesapenas para arquivos.

FreeBSD

$ shasum CONTENTS/
7f986e5e5289c59db1bba48df92ffe4707830aaa  CONTENTS/

Linux

$ shasum CONTENTS/
7f986e5e5289c59db1bba48df92ffe4707830aaa  CONTENTS/

Mac OS

$ shasum CONTENTS/
shasum: CONTENTS/: 

Como eu poderia calcular o hash de um diretório no MacOS?

TENTE 1: Usando TAR com tubos

Tentei usar, mas parece que esta opção tar não funciona no MacOS.

tar cO CONTENTS/ | shasum
tar: Option -O is not permitted in mode -c
da39a3ee5e6b4b0d3255bfef95601890afd80709  -

TENTE 2: Usando FIND/EXEC

Era consistente entre MacOS e FreeBSD, mas o Linux retornou um hash estranho

find CONTENTS -type f -exec shasum {} \; | sort -k 2 | shasum

Linux

c2ddb9bc5f543e956f5cdcc76750cb78cc5f26f3

FreeBSD

3ac2a9d4e2fc5d2d2ec3c7f612e680990cc35824

Mac OS

3ac2a9d4e2fc5d2d2ec3c7f612e680990cc35824

OUTRAS DESCOBERTAS SOBRE TAR

tarseria excelente pois ele "arquiva" uma pasta e então eu poderia shasumfazê-lo, porém a ordem de como tar"andar" a estrutura da pasta énão consistente entre sistemas operacionais. Como alguns ajudantes mencionaram nos comentários que devo usar a mesma versão tarem todos os sistemas.

Apenas um exemplo, no sistema 1 tenho esta ordem:

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

e no sistema 2 tenho a seguinte ordem:

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

Do tarponto de vista está tudo bem, mas devido à ordem, shasumproduz um hash diferente.

CONCLUSÃO

shasumé consistente entre Linux e BSDs para verificar um hash de arquivo individual, mas, quando se trata de diretórios, a consistência acontece apenas no MacOS e FreeBSD, talvez devido à forma como os arquivos são classificados.

Se a classificação for aplicada usando o findcomando, a consistência só será obtida no FreeBSD e MacOS, no entanto, este método é proibitivo em termos de tempo, pois leva uma quantidade significativa de tempo para calcular os hashes para cada arquivo e, em seguida, todo o hash da estrutura.

Usar tarpara criar um arquivo temporário e depois fazer um shasumtambém é inconsistente entre Linux e BSDs, talvez por causa da diferença no método de arquivamento.

Acho que o único caminho a seguir éredesenhar minha solução.

Responder1

mtreeé a ferramenta que você deseja.

Suponha:

$ 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

Crie um manifesto de referência do diretório fooe armazene-o em foo.mtree:

$ mtree -c -K sha256digest -p foo > foo.mtree

Agora vá e mexa em qualquer arquivo nesse diretório.

$ touch foo/date3

Execute mtreenovamente e passe o manifesto que você criou anteriormente, e mtreelhe dirá o que mudou:

$ 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

Quaisquer arquivos ausentes fooou adicionados desde a criação do manifesto também serão relatados:

$ 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

Responder2

Rmlintfará o que (eu acho que é) você quiser.

Pontos relevantes:

  • Ele não usa SHA por padrão, mas pode ser solicitado.
  • Ele pode ser instalado no MacOS via homebrew.
  • Por padrão, ele não calcula uma soma de verificação para um único diretório especificado. Pode-se dizer para calcular somas de verificação para todos os diretórios a partir de um determinado ponto de partida, como forma de encontrar diretórios "duplicados" abaixo desse ponto. Mas, como efeito colateral, também fará exatamente o que você parece estar pedindo.
  • Pode ser um exagero para o que você está procurando e pode demorar um pouco para você descobrir os melhores sinalizadores de opção a serem usados, mas é bastante robusto.
  • Descobrir quais sinalizadores usar pode ser complicado. Obter somas de verificação de diretório é bastante fácil, mas fazê-lonãofazer outras coisas, pode ser complicado. (Embora para ficar claro, na verdade ele não modifica nada. No máximo, ele gera um script de shell, que você pode executar manualmente mais tarde, para modificar as coisas, se desejar. O que parece que você precisa é a saída JSON e/ou CSV arquivos, que fornecerão a soma de verificação do diretório que você está procurando.)

Eu uso o rmlint em um script bash para encontrar diretórios duplicados. Aqui está um comando que fará minimamente o que você deseja e o mínimo possível:

rmlint "base/dir/to/start/from" --see-symlinks --hidden --algorithm=sha256 --types=none,duplicatedirs --no-backup -o csv:log.csv

informação relacionada