sha1sum para un directorio de directorios


33
sha1sum ./path/to/directory/* | sha1sum 

lo anterior se publicó como una forma de calcular una suma de un directorio que contiene archivos. Este comando falla si el directorio incluye más directorios. ¿Hay alguna manera de calcular de forma recursiva el sha1sum de un directorio de directorios de manera universal (sin ajustar un algoritmo personalizado al directorio particular en cuestión)?

Respuestas:


14

Gracias a este post SO -

find . -type f \( -exec sha1sum "$PWD"/{} \; \) | sha1sum

Advertencia: ¡Este código no ha sido probado ! Edite esta pregunta si está mal y puede solucionarlo; Aprobaré tu edición.


Lo siento; No pude resistir! ;-) La recursión es divertida. Por supuesto que hay un camino. Escribiré una respuesta adecuada ahora.
allquixotic

3
Esto no generará el mismo hash para las mismas carpetas exactas en las diferentes máquinas porque la salida también contiene <hash> y <ruta de archivo> qué ruta de archivo es diferente en diferentes máquinas y causa diferentes hash en diferentes máquinas. Línea correcta debe ser como find . -type f \( -exec sha1sum "$PWD"/{} \; \) | awk '{print $1}' | sort | sha1sum@allquixotic
Alper

1
Además de esto, los hash de los archivos deben estar ordenados, lo que también causará diferentes hashes si el orden de clasificación es diferente en diferentes máquinas.
Alper

40

Generalmente me gusta el patrón "encontrar | xargs", así:

find ./path/to/directory/ -type f -print0  | xargs -0 sha1sum

Debe usar "-print0" y "-0", en caso de que haya espacios en los nombres de archivo.

Sin embargo, esto es muy similar al patrón "find -exec cmd {}".

Vea una discusión que compara los dos patrones aquí: https://stackoverflow.com/questions/896808/find-exec-cmd-vs-xargs


Su respuesta solo devuelve el hash de los archivos. El hash de la carpeta se debe obtener usando find . -type f -print0 | xargs -0 sha1sum | awk '{print $1}' | sha1sum.
alper

5

ACTUALIZACIÓN: Han pasado algunos años desde que publiqué esta respuesta y, mientras tanto, reescribí y mejoré el guión que presenté aquí varias veces. He decidido volver a publicar el nuevo script como una respuesta completamente nueva. Lo recomendaría mucho sobre este.

INTRODUCCIÓN

Observé que el orden en que el comando find genera los elementos encontrados dentro de un directorio varía dentro de directorios idénticos en diferentes particiones. Si está comparando los hashes del mismo directorio, no tiene que preocuparse por eso, pero si obtiene los hashes para asegurarse de que no se pierdan ni corrompan archivos durante una copia, debe incluir una línea adicional para ordenando el contenido del directorio y sus elementos. Por ejemplo, la respuesta de Matthew Bohnsack es bastante elegante:

find ./path/to/directory/ -type f -print0  | xargs -0 sha1sum

Pero si lo está usando para comparar un directorio copiado con su original, enviaría la salida a un archivo txt que compararía con la lista de salida del otro directorio usando Kompare o WinMerge o simplemente obteniendo los hashes de cada lista . La cuestión es que, como el orden en que la herramienta de búsqueda generará el contenido puede variar de un directorio a otro, Kompare señalará muchas diferencias porque los hash no se calcularon en el mismo orden. No es un gran problema para los directorios pequeños, pero es bastante molesto si se trata de 30000 archivos. Por lo tanto, debe realizar los pasos adicionales de ordenar la salida para facilitar la comparación de las listas hash entre los dos directorios.

find ./path/to/directory/ -type f -print0  | xargs -0 sha1sum > sha1sum_list_unsorted.txt
sort sha1sum_list_unsorted.txt > sha1sum_list_sorted.txt

Esto ordenaría la salida de modo que los archivos con el mismo hash vayan a estar en las mismas líneas cuando se ejecute el programa de diferenciación (siempre que no falten archivos en el nuevo directorio).

Y EN EL ESCRITO ...

Aquí hay un guión que escribí. Hace lo mismo que hace la respuesta find / xarg, pero ordenará los archivos antes de obtener el sha1sum (manteniéndolos en el mismo directorio). La primera línea del script encuentra todos los archivos dentro del directorio de forma recursiva. El siguiente ordena los resultados alfabéticamente. Los siguientes dos, toman el contenido ordenado y agregan un sha1sum y comillas a los archivos en la lista ordenada, creando un gran script de shell que calcula cada hash de los archivos, uno a la vez y lo envía a content_sha1sum.txt.

#!/bin/bash
find . -type f > content.txt
sort content.txt > content_sorted.txt
awk '{print "sha1sum \""$0}' content_sorted.txt > temp.txt
awk '{print $0"\""}' temp.txt > get_sha1.sh
chmod +x get_sha1.sh
./get_sha1.sh > content_sha1sum.txt
rm content.txt
rm content_sorted.txt
rm temp.txt
rm get_sha1.sh
xdg-open content_sha1sum.txt

Espero que esto ayude.


Cuando la longitud total de todos los nombres de archivo se ajusta a la línea de comando, pasar por sort -z( --zero-terminated) es más fácil que jugar con un montón de archivos.
Anton Samsonov

@AntonSamsonov Este es un script muy antiguo, solo estaba aprendiendo scripting en ese momento. Desde entonces lo he reescrito muchas veces. Con respecto a su comentario, ¿qué hace la terminación cero al ordenar? Leí la página del manual. Dicen que la terminación cero fija un byte cero al final de la línea en lugar de una nueva línea. ¿Qué logra eso?
thebunnyrules

He publicado una actualización de este script como una respuesta separada aquí: superuser.com/questions/458326/...
thebunnyrules

4

INTRODUCCIÓN

Hace unos años, escribí y presenté (en este mismo hilo) un script que puede verificar las firmas hash de todos los archivos individuales en la estructura del directorio actual y mostrarlo como una lista en un archivo de texto.

Desde entonces, he refinado esta fórmula varias veces. He decidido volver a publicar mi script nuevo y mejorado aquí como una respuesta separada. Está escrito para sha256, pero cualquiera que quiera usar sha1 puede hacer una búsqueda simple y reemplazar en gedit para intercambiar sha256 con sha1. Personalmente, no he usado sha1 durante un par de años y no lo recomendaría, ya que está obsoleto y Google ha demostrado cómo puede verse comprometido .

Esto es lo que hace mi nuevo script:

  1. Simplemente puede usar el script yendo al directorio que desea hacer hash e ingresando:

    sha256rec

    Alternativamente, puede llamar a este script desde otro directorio haciendo:

    sha256rec "/path/to/target/directory/you/want/hash"
  2. El script detectará si tiene privilegios de escritura en el directorio actual. Si lo hace, los resultados se guardarán en el directorio actual. Si no tiene privilegios de escritura o si su directorio actual está en un sistema de solo lectura (como un cdrom), los resultados se guardarán en el directorio de inicio del usuario actual.

  3. El script detectará si algunos de los subdirectorios no son accesibles con los privilegios actuales del usuario. Si todos son legibles, entonces no se produce la elevación de privilegios, si no lo son, los privilegios del usuario se elevan a root.

  4. Buscar se utiliza para buscar todos los archivos en la estructura de directorios actual (incluidos todos los subdirectorios). Ordenar se utiliza para asegurarse de que los resultados se emiten alfabéticamente. La lista resultante se somete a sha256sum y se envía a un archivo de texto.

  5. Desde que escribí el antiguo script, adopté una filosofía de diseño de que los archivos temporales son malos y deben evitarse cuando sea posible, ya que dejan a los usuarios abiertos a la intromisión y manipulación por parte de terceros maliciosos. Por lo tanto, todos los datos de este nuevo script se manipulan como variables hasta el último minuto, donde los resultados se superan como un archivo de texto.

  6. El archivo resultante en sí es hash y la ruta / hash se supera en el terminal. Me gusta tomar fotos de estos hashes con una cámara fuera de línea de la vieja escuela para asegurarme de que el archivo de resultados no haya sido alterado cuando lo consulte más adelante.

  7. Los archivos de resultados antiguos se ignoran en el recuento. Facilita la comparación de resultados.

Aquí hay un ejemplo de la salida del terminal cuando ejecuto mi script:

kernelcrunch@ubuntu:/usr/src/linux-headers-4.13.0-16-generic$ sha256rec
======================================================================= 
sha256rec:         
=======================================================================        
Current Folder : /usr/src/linux-headers-4.13.0-16-generic   
Target Folder  : /usr/src/linux-headers-4.13.0-16-generic
Output File    : /home/kernelcrunch/000_sha256sum_recurs_linux-headers-4.13.0-16-generic_d_22-04-2018_t_02.17.txt


Seems you're currently in either a Read-Only system or a root owned directory as a regular user. You can find the hash results in your home folder.
f3ddb06212622c375c6bcc11bd629ce38f6c48b7474054ca6f569ded4b4af9d8  /home/kernelcrunch/000_sha256sum_recurs_linux-headers-4.13.0-16-generic_d_22-04-2018_t_02.17.txt
Operation Length: 10 Seconds.
=======================================================================
kernelcrunch@ubuntu:/usr/src/linux-headers-4.13.0-16-generic$ 

Aquí hay un fragmento de la salida que se puede encontrar en 000_sha256sum_recurs_linux-headers-4.13.0-16-generic_d_22-04-2018_t_02.17.txt:

79c3f378a42bd225642220cc1e4801deb35c046475bb069a96870ad773082805  ./.9491.d
2e336c69cde866c6f01a3495048d0ebc2871dd9c4cb5d647be029e0205d15ce6  ./.config
174f23ff7a7fba897bfb7cf17e9a501bcecacf7ef0c0d5cf030414c1e257d4e3  ./.config.old
389d83f546b250304a9a01bb3072ff79f9d9e380c8a2106cadbf714a872afe33  ./.missing-syscalls.d
035dc77da819101cb9889b4e515023dddd2c953f00d2653b87c6196a6560903e  ./Module.symvers
b28054d7995233e6d003ceb9ed119a0b3354f5ccf77b8d687fc0353ae3c5bfb8  ./arch/x86/include/generated/asm/.syscalls_32.h.cmd
01cf821170e3e6e592e36a96e8628377151c762ac2ee3210c96004bfaef22f5f  ./arch/x86/include/generated/asm/.syscalls_64.h.cmd
111efa83187c58a74a9b0170fd496b497b0682d109a7c240c17e2ffcc734f4f4  ./arch/x86/include/generated/asm/.unistd_32_ia32.h.cmd
fcba4e8abf9e95472c31708555db844ac43c87260fb0ba706b6f519404bf9aba  ./arch/x86/include/generated/asm/.unistd_64_x32.h.cmd
3264438a54cbf7e62b05d38a93c5df8fe4202ac782a5d83ed202cba9eee71139  ./arch/x86/include/generated/asm/.xen-hypercalls.h.cmd
4bd7a45837da7de379b87242efe562ce06bf9d8ab8f636c205bb5ef384c8f759  ./arch/x86/include/generated/asm/clkdev.h
0d96461abd23bbf2da522822948455413a345f9ef8ac7a7f81c6126584b3c964  ./arch/x86/include/generated/asm/dma-contiguous.h
b1a54c24a12ce2c0f283661121974436cdb09ae91822497458072f5f97447c5d  ./arch/x86/include/generated/asm/early_ioremap.h
dd864107295503e102ea339e0fd4496204c697bdd5c1b1a35864dfefe504a990  ./arch/x86/include/generated/asm/mcs_spinlock.h
782ce66804d000472b3c601978fa9bd98dcf3b2750d608c684dc52dd1aa0eb7e  ./arch/x86/include/generated/asm/mm-arch-hooks.h
cd9913197f90cd06e55b19be1e02746655b5e52e388f13ec29032294c2f75897  ./arch/x86/include/generated/asm/syscalls_32.h
758ce35908e8cfeec956f57a206d8064a83a49298e47d47b7e9a7d37b5d96d59  ./arch/x86/include/generated/asm/syscalls_64.h
1147ca3a8443d9ccbdf9cd1f4b9b633f0b77f0559b83ec5e4fa594eadb2548be  ./arch/x86/include/generated/asm/unistd_32_ia32.h
ca5223fbf8f03613a6b000e20eb275d9b8081c8059bc540481a303ce722d42f3  ./arch/x86/include/generated/asm/unistd_64_x32.h
31703052c0d2ab8fe14b4e5dfcc45fcbd5feb5016b0a729b6ba92caa52b069e2  ./arch/x86/include/generated/asm/xen-hypercalls.h
c085ff1b6e9d06faa3fc6a55f69f9065c54098d206827deec7fe0a59d316fc99  ./arch/x86/include/generated/uapi/asm/.unistd_32.h.cmd
7929c16d349845cebb9e303e0ff15f67d924cac42940d0f7271584f1346635fc  ./arch/x86/include/generated/uapi/asm/.unistd_64.h.cmd
9aa492c5a75f5547f8d1dc454bef78189b8f262d1c4b00323a577907f138a63e  ./arch/x86/include/generated/uapi/asm/.unistd_x32.h.cmd
f568e151bbbb5d51fd531604a4a5ca9f17004142cd38ce019f0d5c661d32e36b  ./arch/x86/include/generated/uapi/asm/unistd_32.h
c45cf378498aa06b808bb9ccf5c3c4518e26501667f06c907a385671c60f14ae  ./arch/x86/include/generated/uapi/asm/unistd_64.h
a0088d8d86d7fd96798faa32aa427ed87743d3a0db76605b153d5124845161e2  ./arch/x86/include/generated/uapi/asm/unistd_x32.h
e757eb6420dffa6b24b7aa38ca57e6d6f0bfa7d6f3ea23bbc08789c7e31d15fa  ./arch/x86/kernel/.asm-offsets.s.cmd
f9e703e4f148d370d445c2f8c95f4a1b1ccde28c149cff2db5067c949a63d542  ./arch/x86/kernel/asm-offsets.s
7971fb3e0cc3a3564302b9a3e1ad188d2a00b653189968bbc155d42c70ce6fbf  ./arch/x86/purgatory/.entry64.o.cmd
8352d79fe81d2cf694880f428e283d79fd4b498cea5a425644da25a9641be26b  ./arch/x86/purgatory/.kexec-purgatory.c.cmd
37f3edbee777e955ba3b402098cb6c07500cf9dc7e1d44737f772ac222e6eb3e  ./arch/x86/purgatory/.purgatory.o.cmd
bb8b895cbd2611b69e2f46c2565b4c2e63a85afb56cff946a555f2d277ee99b2  ./arch/x86/purgatory/.purgatory.ro.cmd
bcc2365c9d3d027f1469806eb4f77b0f3ede6eb0855ea0fcd28aa65884046a54  ./arch/x86/purgatory/.setup-x86_64.o.cmd
872229f334fdcc8562e31b9f6581008c1571ac91f12889cd0ff413590585155a  ./arch/x86/purgatory/.sha256.o.cmd
6fb0cbef120aadee282f7bc3b5ea2f912980f16712281f8f7b65901005194422  ./arch/x86/purgatory/.stack.o.cmd
cd1b61063ae3cf45ee0c58b2c55039f3eac5f67a5154726d288b4708c4d43deb  ./arch/x86/purgatory/.string.o.cmd
e5826f0216fd590972bbc8162dd175f87f9f7140c8101505d8ca5849c850ec91  ./arch/x86/purgatory/entry64.o

(continúa con otras 7000+ líneas como esta, pero se entiende la idea)

INSTALACIÓN

  1. Abra una terminal e ingrese los siguientes comandos:

    cd /usr/bin
    sudo su
    echo '#!/bin/bash'> /usr/bin/sha256rec
    chmod +x /usr/bin/sha256rec
    touch /usr/bin/sha256rec
    nano /usr/bin/sha256rec
  2. En nano, use Shif + Ctrl + v para pegar. Ctrl-O e Enter para guardar. Ctr-X sale. Pegue mi script allí:

(pegar después de #! / bin / bash)

  #FUNCTIONS OR FUNCTYOU?
  function s_readonly { err=$(date +%s%N); cd "$1"; mkdir $err 2> /tmp/$err; rmdir $err 2>/dev/null; echo $(cat /tmp/$err|grep -i "Read-only file system"|wc -l);shred -n 0 -uz /tmp/$err; }
  function w_denied { echo $(err=$(date +%s%N); cd "$1"; mkdir $err 2> /tmp/$err; rmdir $err 2>/dev/null; cat /tmp/$err|grep -i "Permission denied"|wc -l;shred -n 0 -uz /tmp/$err); }
  function r_denied { echo $(err=$(date +%s%N); cd "$1" >/dev/null 2> /tmp/$err; find . >/dev/null 2>> /tmp/$err; cat /tmp/$err|grep -i "Permission denied"|wc -l;shred -n 0 -uz /tmp/$err); }
  function rando_name { rando=$(echo $(date +%s%N)|sha256sum|awk '{print $1}'); rando=${rando::$(shuf -i 30-77 -n 1)}; echo $rando;}
  function ms0 { ms0=$(($(date +%s%N)/1000000)); }; function mstot { echo $(($(($(date +%s%N)/1000000))-$ms0));}
  function s0 { s0=$(date +%s); }; function stot { echo $(($(date +%s)-$s0));}
  s0

  #CHECK IF A TARGET DIR WAS SPECIFIED (-t= or --target= switch)
  if [ ! -z "$1" ]; then arg1="$1"; arg1_3=${arg1::3}; arg1_9=${arg1::9};fi
  if [ "$arg1_3" = "-t=" -o "$arg1_9" = "--target=" ]; then 
    switch=$(echo $arg1|awk -F '=' '{print $1}')
    switch_chr=$((${#switch}+1))
    target=${arg1:$switch_chr}
    current=$(pwd)
    cd "$target"
    arg1="" #<- cancels the not path in the find line
  else
    current=$(pwd)
    target=$(pwd) 
  fi

  echo -e  "=======================================================================\
    \nsha256rec: \
          \n=======================================================================\
          \nCurrent Folder : $current \
    \nTarget Folder  : $target"

  #GETS DEFAULT_USER, ASSUME'S YOU'RE USER 1000, IF 1000 DOESN'T EXIST SEARCHES 999, THEN 1001, 1002
  default_user=$(awk -v val=1000 -F ":" '$3==val{print $1}' /etc/passwd)
  if [ -z "$default_user" ]; then default_user=$(awk -v val=999 -F ":" '$3==val{print $1}' /etc/passwd); fi
  if [ -z "$default_user" ]; then default_user=$(awk -v val=1001 -F ":" '$3==val{print $1}' /etc/passwd); fi
  if [ -z "$default_user" ]; then default_user=$(awk -v val=1002 -F ":" '$3==val{print $1}' /etc/passwd); fi

  if [ "$(users | wc -l)" = "1" ]; then USER=$(users|awk '{print $1}'); else USER=$default_user;fi #not perfect but meh...

  #running rando_name in this very specific spot between USER detection and Permission detection, some interfers somehow with detection functions... 
  #the rando function placed underneath the user detection is somehow turning c=$current from the dir path to whatever rando_name puts out.

  #FIGURE OUT WHERE TO PUT HASH LIST
  hash_file="000_sha256sum_recurs_${target##*/}_d_$(date +%d-%m-20%y)_t_$(date +%H.%M).txt"
  if [ $(s_readonly "$current") -gt 0 -o $(w_denied "$current") -gt 0 ]; then if [ "$(whoami)" != root ]; then dest="/home/$(whoami)";echo -e "Output File    : $dest/$hash_file\n\n";echo "Seems you're currently in either a Read-Only system or a root owned directory as a regular user. You can find the hash results in your home folder."; else dest="/home/$USER";echo -e "Output File    : $dest/$hash_file\n\n";echo "Seems you're currently a Read-Only system. You can find the hash results in $USER's home folder.";fi; else dest="$current";echo -e "Output File    : $dest/$hash_file\n\n";echo "Results will be saved here.";fi



  #CAN REGULAR USER ACCESS TARGET DIR? ARE ALL IT'S SUBDIRS READABLE?
  if [ $(r_denied "$target") -gt 0 ]; then sudo=sudo; echo "Some folder were not read-able as a regular user. User elevation will be required.";fi

  #PERFORM RECURSIVE HASHING
  command=$($sudo find . -type f -not -type l -not -path "$arg1"  -not -path "$2"  -not -path "$3" -not -path "$4"  -not -path "$5"  -not -path "$6" -not -path "$7"  -not -path "$8"  -not -path "$9" |grep -v "\./000_sha"|sort|awk "{print \"$sudo sha256sum \\\"\"\$0}"|awk '{print $0"\""}'|tr '\n' ';')
  eval $command > "$dest/$hash_file"

  sha256sum "$dest/$hash_file"
  echo "Operation Length: $(stot) Seconds."
  echo -e  "======================================================================="



  if [ "$target" != "$current" ]; then cd "$current";fi


  exit
  #||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
  #||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
  #||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
  #||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
  1. Cuando salga de nano, asegúrese de salir del estado elevado ingresando:

    exit

PENSAMIENTOS FINALES

  1. Esto solo funcionará si tiene instalado bash. He usado algunos Synthax para la manipulación de subcadenas que no funcionan con sh, dash, ksh o zsh. Todavía puede usar cualquiera de los otros shells como controladores diarios, pero es necesario instalar bash.

  2. Las listas de salida se pueden comparar con una variedad de herramientas como: (en el terminal) diff, sdiff (y gráfico) difuso, kdiff, winmerge.

  3. Mi archivo ordena la salida en función de la ruta, para que sea más fácil de leer por los humanos. He notado que el comando de clasificación funciona de manera diferente en diferentes distribuciones. Por ejemplo, en una distribución, las letras de MAYÚSCULAS tenían prioridad sobre las no mayúsculas y en la otra no. Esto afecta el orden de las líneas de los archivos de salida y podría dificultar la comparación de los archivos. Esto no debería presentar ningún problema si siempre usa el script en la misma distribución, pero puede hacerlo si se generaron listas hash en dos entornos diferentes. Esto se soluciona fácilmente clasificando los archivos hash una vez más para que las líneas se ordenen por hash en lugar de ruta:

     cat 000_sha256sum_oldhashlist|sort> ./old
     cat 000_sha256sum_newhashlist|sort> ./new
     sha256sum ./old ./new; diff ./old ./new

Una línea shebang más robusta sería #!/usr/bin/env bash: también encontrará Bash en otros directorios, porque este último puede instalarse en / usr / bin en lugar de / bin , por ejemplo, mientras que env tiende a estar en / usr / bin en todo momento hasta donde me di cuenta. También vale la pena señalar que, dado que necesita Bash, puede usar [[ blah-blah ]]una expresión condicional de doble paréntesis en lugar de una [ blah-blah ]variante genérica de un solo paréntesis.
Anton Samsonov

Gracias por los consejos. Acabo de terminar de buscar los [[condicionales. Se ven realmente útiles.
thebunnyrules

La preocupación por el compromiso de SHA1 no es realmente aplicable en el caso de comparar archivos después de copiar para verificar la integridad. Las posibilidades de que un archivo se corrompa en tránsito pero aún tenga el mismo SHA1 son prácticamente nulas. Si sospecha que un atacante podría haber tenido tiempo suficiente para generar un archivo diferente con un SHA1 en colisión, use SHA256, pero para el caso típico de copiar archivos, es excesivo y más lento que SHA1 o MD5 .
Dan Dascalescu

Tu propio argumento puede ser usado contra sí mismo. Si le preocupa la corrupción normal (no relacionada con el ataque), entonces sha1 es excesivo. Puede obtener resultados más rápidos con md5 / crc32. En cualquier situación (detección de manipulación o corrupción) sha1 no es una buena opción. Personalmente, uso estas listas de hash para ambos escenarios y no he notado ningún impacto perceptible en el rendimiento desde que actualicé a sha256, pero tampoco estoy ejecutando un mega servidor. Como dije en la respuesta, puedes usar cualquier hash que quieras reemplazando mi comando sha256sum por el que quieras: sha1sum, md5sum, b2sum, crc32 ...
thebunnyrules

1

Esto parece funcionar para mí:

find . \( -not -name . \) -type f -exec cat {} + | sha1sum

EDITAR: esto solo mostrará todos los archivos contenidos en el árbol de directorios. Si se cambiara el nombre de un directorio, esto no lo detectaría. Tal vez algo como:

find . -exec sha1sum {} + 2>&1 | sha1sum

Lo haría. Aunque casi la misma respuesta que la otra


1

Otro truco podría ser usar tar para trocear los contenidos y metadatos del archivo:

tar -cf - ./path/to/directory | sha1sum

lástima que solo tenga un voto
166_MMX

1
Esto no funciona. tar incluye una marca de tiempo para algunos sistemas operativos (como OSX) y el sha1sum será diferente en cada ejecución.
srossross

Lo que dijo @srossross. Además, si tiene diferentes versiones de tar en los dos hosts, las salidas serán diferentes.
Dan Dascalescu

1

Solución rápida, robusta y portátil.

A diferencia de algunas de las otras soluciones involucradas tar, la siguiente solución funciona en cualquier máquina que tenga las utilidades estándar de Unix, y es más rápida que todas las demás soluciones al paralelizar la suma de comprobación:

find . -type f | xargs -d'\n' -P0 -n1 md5sum | sort -k 2 | md5sum

Como utiliza una ordenación al final, no hay progreso en tiempo real, así que solo deje que se ejecute el comando.

Esto es lo que hacen los argumentos:

  • find . -type f encuentra todos los archivos en el directorio actual y sus subdirectorios
  • xargs -d'\n'divide la salida de find en líneas (si espera tener archivos con nuevas líneas, entonces haga lo habitual find -print0 | xargs -0)
  • -P0 n1se ejecuta md5sumen procesos paralelos, utilizando el número máximo de procesos admitidos por la máquina (¡multi-núcleo!)
  • sort -k 2ordena por el segundo campo de la md5sumsalida, que es la ruta completa a cada archivo (el primero es el MD5)
  • el final md5sumcalcula una suma de comprobación de la lista de sumas de comprobación de archivos, de modo que obtiene una suma de comprobación del directorio completo en una línea, que puede comparar fácilmente visualmente en las ventanas de terminal

Antes de decir que "MD5 ha sido comprometido", recuerde cuál es su modelo de amenaza. ¿Está tratando de asegurarse de que los archivos que copió de algún otro host o disco llegaron intactos? Entonces MD5 es más que suficiente, porque las posibilidades de que un archivo se corrompa en tránsito pero tenga el mismo MD5 son cero. Pero si tiene miedo de que un atacante tenga tiempo para reemplazar un archivo por otro diferente con una suma de verificación colisionante, entonces úselo sha256sum. La desventaja es que las funciones SHA son más lentas que MD5 .

Progreso detallado en tiempo real

Finalmente, si desea ver el progreso en tiempo real, modifique la canalización para usar un archivo temporal para las sumas de verificación:

find . -type f | xargs -d\\n -P0 -n1 md5sum | tee /tmp/sums && sort -k 2 /tmp/sums | md5sum

(Tenga en cuenta que mover el sortderecho después findno funcionaría, ya que xargs -P0paraleliza md5sumy los resultados pueden llegar fuera de orden)

Esta versión del comando también le permite diferenciar los dos /tmp/sumsarchivos (asegúrese de cambiar el nombre del segundo si está en la misma máquina) y ver qué archivos difieren.


0

En lugar de tener UN archivo enorme que contiene toda la información hash, estaba buscando una manera de hacer un archivo en cada carpeta de un árbol. Me inspiré en los comentarios aquí. El mío es un poco más complejo de lo que se publica aquí. Uso la rotación de archivos, pero este es el menos complejo para los nuevos jugadores. Esta versión tendrá que sobrescribir las sumas de cheques antiguas con las nuevas. Puede ser bueno mantener 2-3 versiones dependiendo de la frecuencia con la que lo ejecute y su necesidad de 'profundidad'.

[usuario @ host bin] $ cat mkshaindir 
#! / bin / dash
cd $ 1
sha512sum *> .sha512sum

[usuario @ host bin] $ find / var / tmp -type d -print0 | xargs -0 -i mkshaindir {}

Tenga en cuenta que mkshaindir, para mis propósitos, es un componente separado porque es posible que necesite crear un hash de archivos en una nueva carpeta, o de uno que se modificó recientemente. Todo esto se puede combinar en un script si es necesario.

El resto se deja como ejercicio para el lector.


0

basado en la respuesta anterior :

find ./path/to/directory -print0 | LC_ALL=C sort --zero-terminated | tar --create --no-recursion --null --files-from /dev/stdin --file /dev/stdout --verbose --numeric-owner | sha1sum

  • tipo estable
  • propietario numérico e identificación del grupo
  • progreso detallado
  • nombre de archivo seguro

Esto no funcionó en un directorio copiado que contenía solo un archivo, y sospecho que fue porque estaba ejecutando una versión ligeramente más antigua de tar (1.28) en el host remoto, frente a 1.29 en el host local. Por desgracia, el alquitrán 1.29 no se ha portado en Xenial.
Dan Dascalescu

0

@allquixoticLa respuesta no genera los mismos hashes en diferentes máquinas que no nos ayudarán a verificar y tener hashes consistentes.

La siguiente línea find . -type f \( -exec md5sum "$PWD"/{} \; \)devuelve el siguiente resultado:

d41d8cd98f00b204e9800998ecf8427e  /home/helloWorld.c
24811012be8faa36c8f487bbaaadeb71  /home/helloMars.c

Por lo tanto, el camino sería diferente en diferentes máquinas. awk '{print $1}'nos ayudará a obtener la primera columna, que solo tiene el hash de los archivos. Más tarde, debemos ordenar esos hashes, donde el orden puede ser diferente en diferentes máquinas, lo que también puede hacer que tengamos diferentes hashes si hay más de dos archivos.


Solución:

Para Mac:

find ./path/to/directory/ -type f \( -exec md5 -q  "$PWD"/{} \; \) | awk '{print $1}' | sort | md5

Para Linux:

find ./path/to/directory/ -type f \( -exec md5sum "$PWD"/{} \; \) | awk '{print $1}' | sort | md5sum | awk '{print $1}'
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.