Estou escrevendo um script de shell que usa shasum
para verificar se o conteúdo de um diretório foi alterado.
No Linux e no FreeBSD, eles shasum
têm o mesmo comportamento quando eu o faço shasum <directory>
, no entanto, no MacOS, eles shasum
me 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
tar
seria excelente pois ele "arquiva" uma pasta e então eu poderia shasum
fazê-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 tar
em 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 tar
ponto de vista está tudo bem, mas devido à ordem, shasum
produz 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 find
comando, 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 tar
para criar um arquivo temporário e depois fazer um shasum
també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 foo
e 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 mtree
novamente e passe o manifesto que você criou anteriormente, e mtree
lhe 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 foo
ou 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