Tengo un directorio con varios archivos img y algunos de ellos son idénticos, pero todos tienen nombres diferentes. Necesito eliminar duplicados pero sin herramientas externas solo con un bashscript. Soy un principiante en Linux. Intenté anidar para el bucle para comparar md5sumas y, dependiendo del resultado, eliminar, pero algo está mal con la sintaxis y no funciona. ¿alguna ayuda?
lo que he intentado es ...
for i in directory_path; do
sum1='find $i -type f -iname "*.jpg" -exec md5sum '{}' \;'
for j in directory_path; do
sum2='find $j -type f -iname "*.jpg" -exec md5sum '{}' \;'
if test $sum1=$sum2 ; then rm $j ; fi
done
done
Yo obtengo: test: too many arguments
bash
shell-script
linuxbegin
fuente
fuente

Respuestas:
Hay bastantes problemas en su script.
En primer lugar, con el fin de asignar el resultado de un comando a una variable que necesita para encerrarlo ya sea en backtics (
`command`) o, preferiblemente,$(command). Lo tiene entre comillas simples ('command') que, en lugar de asignar el resultado de su comando a su variable, asigna el comando en sí como una cadena. Por lo tanto, tutestes en realidad:El siguiente problema es que el comando
md5sumdevuelve más que solo el hash:Solo desea comparar el primer campo, por lo que debe analizar el
md5sumresultado pasándolo a través de un comando que solo imprime el primer campo:o
Además, el
findcomando devolverá muchas coincidencias, no solo una y cada una de esas coincidencias se duplicará por la segundafind. Esto significa que en algún momento comparará el mismo archivo consigo mismo, el md5sum será idéntico y terminará eliminando todos sus archivos (ejecuté esto en un directorio de prueba que contienea.jpgyb.jpg):No desea ejecutar a
for i in directory_pathmenos que esté pasando una serie de directorios. Si todos estos archivos están en el mismo directorio, desea ejecutarfor i in $(find directory_path -iname "*.jpg") para revisar todos los archivos.Es una mala idea usar
forbucles con la salida de find. Debe usarwhilebucles o globbing :o, si todos sus archivos están en el mismo directorio:
Dependiendo de su shell y las opciones que haya configurado, puede usar globbing incluso para archivos en subdirectorios, pero no entremos en eso aquí.
Finalmente, también debe citar sus variables; de lo contrario, las rutas de directorio con espacios romperán su script.
Los nombres de archivo pueden contener espacios, nuevas líneas, barras invertidas y otros caracteres extraños, para tratarlos correctamente en un
whilebucle necesitará agregar algunas opciones más. Lo que quieres escribir es algo como:Una forma aún más simple sería:
Una mejor versión que puede manejar espacios en los nombres de archivo:
Este pequeño script de Perl se ejecutará a través de los resultados del
findcomando (es decir, el md5sum y el nombre del archivo). La-aopción paraperldividir líneas de entrada en espacios en blanco y guardarlas en laFmatriz,$F[0]será md5sum y$F[1]el nombre del archivo. El md5sum se guarda en el hashky el script comprueba si el hash ya se ha visto (if $k{$F[0]}>1) y elimina el archivo si lo tiene (system("rm $F[1]")).Si bien eso funcionará, será muy lento para grandes colecciones de imágenes y no puede elegir qué archivos guardar. Hay muchos programas que manejan esto de una manera más elegante, incluyendo:
fdupesfslintfuente
unlinklugar de hacer unasystemllamada.$F[1]. Se solucionó utilizando rebanadas de matriz. En cuanto a unlink (), lo sé, pero quería mantener los perlismos al mínimo y la llamada al sistema es más fácil de entender si no conoce a Perl.Hay un programa ingenioso llamado
fdupesque simplifica todo el proceso y solicita al usuario que elimine los duplicados. Creo que vale la pena verificarlo:Básicamente, me solicitó qué archivo guardar , escribí 1 y eliminó el segundo.
Otras opciones interesantes son:
A partir de su ejemplo, probablemente quiera ejecutarlo como:
Ver
man fdupespara todas las opciones disponibles.fuente