Compare a pasta com a estrutura de pastas

1

Eu tenho o cartão SD da minha câmera com fotos e filmes. Na minha home box, eu tenho uma estrutura de pastas com nomes de diretórios como este: images / YYYY-MM-description, algumas vezes existem subpastas com nomes variados abaixo. Os nomes de arquivos dos arquivos no cartão SD são os mesmos nomes de arquivos das pastas.

Gostaria de comparar (checksum) o cartão SD com a estrutura de pastas para descobrir se a minha caixa tem todos os arquivos no cartão SD. Pensei em MD5ing-los, mas qualquer algoritmo que se encaixa no caso de uso faria.

Eu pensei em usar rsync ou diff , mas não consigo encontrar uma solução por causa da estrutura de vários níveis na minha caixa.

O sistema é Debian wheezy, no caso de ser importante.

    
por Jan 17.08.2015 / 08:59

2 respostas

2

Você pode usar o md5deep.

sudo apt-get install md5deep

Primeiro, salve os resultados de uma das suas pastas:

md5deep -r -s /dir1> dir1sums

Agora compare aqueles com a outra pasta:

md5deep -r -X dir1sums /dir2

Se não houver saída, significa que os diretórios são idênticos. Caso contrário, exibirá os hashes de arquivos diferentes.

    
por 17.08.2015 / 12:30
2

Vou fazer as seguintes suposições:

1) todos os nomes de arquivos são únicos

2) Você só deseja verificar arquivos ausentes (não se os arquivos tiverem a mesma soma md5 em cada dispositivo, ou seja, se uma foto estiver corrompida)

3) Os arquivos só podem estar faltando na máquina, o cartão SD tem todos os arquivos por padrão

Além da suposição de formulário 1, o script pode ser alterado para localizar arquivos únicos em qualquer local ou até mesmo fazer uma verificação cruzada de md5 para cada par de arquivos.

Dessa forma, podemos usar find , selecionar todos os nomes de arquivos e verificar as listas de uniq ue nomes de arquivos

#!/bin/bash

#load all file names from local dir as array:
pics_local=( $( find /path/to/dir/ -type f -printf "%f\n" ) )
#load all file names from SD card as array:
pics_SD=( $( find /mnt/SD/ -type f -printf "%f\n" ) )
#see if files are only in one of them,
#i.e. if file names appear only once (save as array):
singulars=( $( printf "%s\n" ${pics_local[@]} ${pics_SD[@]} |\
            sort | uniq -u ) )
#print list of missing files with full paths using find:
for (( i=0 ; i<=${#singulars[@]}-1 ; i++ )) ; do
    find /mnt/SD/ -type f -name "${singulars[$i]}"
done

ATUALIZAÇÃO: script com md5sum para cada arquivo: Temos todos os arquivos no SD e procuramos os ausentes no diretório local. Todos os arquivos locais são idênticos aos SD (sem arquivos correspondentes com diferença de soma md5)

#!/bin/bash

#load file names and md5sums of files on SD card into array
files_SD=( $( find /mnt/SD/ -type f ) )
md5_SD=( $( find /mnt/SD/ -type f -exec md5sum {} + | cut -d' ' -f1 ) )
#load md5sums of files in local folder into array:
md5_loc=( $( find /local/dir/ -type f -exec md5sum {} + | cut -d' ' -f1 ) )

#check for the very unlikely possibility of md5sums
#matching for more than two files
#IMHO: can be safely skipped
if [[ $(sort <( printf '%s\n' ${md5_loc[@]} ${md5_SD[@]}) |\
      uniq -c | awk ' $1 >= 3 ' ) ]] ; then
  echo "md5 sums matching for more than 2 files!"
  echo "critical error, aborting"
  exit
fi

singular_md5s=( $( printf '%s\n' ${md5_loc[@]} ${md5_SD[@]} | sort | uniq -u ) )
for (( i=0 ; i<=${#singular_md5[@]}-1 ; i++ )) ; do
  #assume SD card has all files
  #print file that is missing in local folder:
  #1) find where it is in the array:
  n=$(( $(grep -n "${singular_md5s[$i]}" <( printf '%s\n' ${md5_SD[@]} ) | cut -d: -f1 )-1 ))
  #2) print file name
  echo "${files_SD[$n]} missing on local folder"
done
    
por 17.08.2015 / 13:02