Estou tentando comparar todos os arquivos em duas pastas por meio de um md5sum em um comando. Alguns gostam do seguinte (bash) no Debian:
$ cd ~/FOLDER1
$ md5sum ~/FOLDER2/* | md5sum -c -
A ideia é que a saída dos hashes do primeiro md5sum seja passada para o segundo e usada como arquivo de entrada. No entanto, o teste mostra que ele apenas compara cada arquivo na FOLDER2 consigo mesmo e retorna "OK" para cada um. Acho que a razão pela qual isso não está funcionando é porque a saída dos nomes dos arquivos do primeiro md5sum inclui o caminho completo. Eu olhei, md5deep
mas não encontrei nada que me ajudasse lá. Eu sei que é possível fazer o md5sum para uma pasta, gravar os resultados em um arquivo e depois usar esse arquivo como entrada para o segundo md5sum. Eu queria fazer tudo em uma linha por meio de um canal, em vez de usar dois comandos e escrever um arquivo.
Editar: a resposta aceitaaqui(usando diff
) pode fazer o que eu quero, mas não sei se diff
(corretamente) compara arquivos binários.
Editar: para obter a saída que eu queria usando md5sum (que mostra o nome do arquivo e "OK"), recorri à gravação de um arquivo em lote. Execute com diffFolders.sh ~/FOLDER1 ~/FOLDER2
.
#!/bin/bash
HERE=$PWD
cd "$1"
md5sum * > /tmp/md5sum.cmp
cd "$2"
md5sum -c /tmp/md5sum.cmp
cd $HERE
Este script comparará apenas arquivos presentes em ~/FOLDER
. Se ~/FOLDER2
houver arquivos adicionais, eles não serão comparados e nenhuma saída indicará que eles existem.
Responder1
Você pode usarsubstituição de processopara passar a saída dos 2 md5sum para diff. Diff, neste caso, seria bom porque as saídas do MD5 são texto simples. Algo como:
diff <(md5 ~/FOLDER1/* | awk '{print $4}') <(md5 ~/FOLDER2/* | awk '{print $4}')
Desculpe, não tenho Debian aqui e não posso testar isso nele. O texto acima foi testado no OS X que possui md5, que pode ser um pouco diferente em termos de saída. No OS X, a quarta coluna do md5 é a soma real do md5, é por isso que estou pegando apenas essas colunas.
Em vez de awk, você também pode usar cut
, mas pode ser necessário alterar o separador para obter a quarta coluna (elas não são separadas por tabulações).
Responder2
Do meu arquivo .bashrc.
coisas muito antigas, deve ser possível escrever muito código de classificação. Nunca tive tempo de reescrevê-lo. (como tudo o mais que foi feito para uma correção temporária, usado para sempre) Estou postando este código vergonhoso, espero que alguém possa fazer melhor e postar o resultado :-)
Características :
- Dir transversal recrusivo
- md5sum verifica exclusividade/diferença
- Lista os arquivos atualizados no caminho completo
O código diz tudo. arg1 é o diretório antigo, arg2 é o novo diretório.
function find-updated-files-between-old-new(){
[ ! -d "$1" ] || [ ! -d "$2" ] && echo "*** Error: The directory is not found." > /dev/stderr && return 1;
( ( cat <(cd "$1";find . -type f -printf "+%p\n") <(cd "$2";find . -type f -printf "-%p\n")
)|sort -k1.2|tee 1>/dev/null >(uniq -us1|awk -v B="$2" 'BEGIN{sub("/$",""B)}/^-/{print B substr($0,3);
}') >(uniq -ds1|awk -vA="$1" -vB="$2" 'BEGIN{B=g(B);A=g(A)}{
C=substr($0,3);if(f(A)!=f(B))print B C;}function g(y){sub("/$","",y);return y}
function f(y,z,e){e="md5sum \""y""C"\"";e|getline z;close(e);return substr(z,1,32)}' )
) | cat
}
Como o nome da função indica
function find-files-name-collision-between-dir1dir2(){
[ ! -d "$1" ] || [ ! -d "$2" ] && echo "*** Error: The directory is not found." > /dev/stderr && return 1;
( cat <(cd "$1";find . -type f -printf "+%p\n") <(cd "$2";find . -type f -printf "-%p\n") )|sort -k 1.2 | uniq -d -s 1
}
Apenas para completar
function mv-mergedir1todir2(){
[ ! -d "$1" ] || [ ! -d "$2" ] && echo "*** Error: The directory is not found." && return 1;
( cd "$1" ; tar cf - . ) | (cd "$2" ; tar --keep-old-files xvf - )
echo -e "Done. Duplicate filnames are not replaced. \n#Use \n# ( cd \"$1\" ; tar cf - . ) | (cd \"$2\" ; tar --overwrite xvf - ) \n#if you do not like that. "
}
Este horrível pedaço de código deveria ser removido do meu bashrc, porém ele já existe há muito tempo...
Responder3
Meio longo, mas retorna o nome do arquivo e OK se corresponderem. Em vez de usar '-c', basta comparar as duas strings resultantes da execução do md5sum no arquivo de cada pasta.
for f in *; do [[ -f $f ]] && if [ $(md5sum "$f" | cut -d" " -f1) == $(md5sum dir2/"$f" | cut -d" " -f1) ]; then echo "$f" "OK"; else echo "$f" "MODIFIED"; fi; done