Estoy intentando comparar todos los archivos en dos carpetas mediante un md5sum en un solo comando. A algunos les gusta lo siguiente (bash) en Debian:
$ cd ~/FOLDER1
$ md5sum ~/FOLDER2/* | md5sum -c -
La idea es que la salida de los hashes del primer md5sum se pase al segundo y se utilice como archivo de entrada. Sin embargo, las pruebas de esto muestran que simplemente compara cada archivo en la CARPETA2 consigo mismo y devuelve "OK" para cada uno. Creo que la razón por la que esto no funciona es porque los nombres de archivo resultantes del primer md5sum incluyen la ruta completa. He mirado md5deep
pero no he encontrado nada que me ayude allí. Sé que es posible hacer md5sum para una carpeta, escribir los resultados en un archivo y luego usar ese archivo como entrada para el segundo md5sum. Quería hacerlo todo en una línea a través de una tubería, en lugar de usar dos comandos y escribir un archivo.
Editar: la respuesta aceptadaaquí(usar diff
) podría hacer lo que quiero, pero no sé si diff
compara (correctamente) archivos binarios.
Editar: para obtener el resultado que quería usando md5sum (que muestra el nombre del archivo y "OK"), recurrí a escribir un archivo por lotes. Ejecutar con 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 solo comparará archivos que estén presentes en formato ~/FOLDER
. Si ~/FOLDER2
tiene archivos adicionales, estos no se compararán y ningún resultado indicará que existen.
Respuesta1
Puedes usarsustitución de procesospara pasar la salida de los 2 md5sum a diff. Diff en este caso estaría bien porque las salidas de md5 son texto sin formato. Algo como:
diff <(md5 ~/FOLDER1/* | awk '{print $4}') <(md5 ~/FOLDER2/* | awk '{print $4}')
Lo siento, no tengo Debian aquí y no puedo probarlo. Lo anterior se prueba en OS X que tiene md5, que puede ser ligeramente diferente en términos de salida. En OS X, la cuarta columna de md5 es la suma real de md5, por eso estoy tomando solo estas columnas.
En lugar de awk, también puedes usar cut
, pero es posible que tengas que cambiar el separador para obtener la cuarta columna (no están separadas por tabulaciones).
Respuesta2
De mi archivo .bashrc.
cosas muy viejas, debería ser posible escribir mucho código clasificador. Nunca logré reescribirlo. (como todo lo demás que estaba destinado a una solución temporal, usado para siempre) Estoy publicando este vergonzoso fragmento de código, espero que alguien pueda hacerlo mejor y publicar el resultado :-)
Características :
- Dir transversal recrusivo
- md5sum comprueba la unicidad/diferencia
- Enumera los archivos actualizados en la ruta completa
El código lo dice todo. arg1 es el directorio antiguo, arg2 es el directorio nuevo.
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 lo indica el nombre de la función
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
}
Sólo 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 horrible fragmento de código debería eliminarse de mi bashrc, sin embargo, ha existido durante mucho tiempo...
Respuesta3
Un poco largo pero devuelve el nombre del archivo y está bien si coinciden. En lugar de usar '-c', simplemente compara las dos cadenas resultantes de ejecutar md5sum en el archivo de cada carpeta.
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