fslint fotos eliminar duplicados duplicadas buscar archivos linux bash command-line find filesystems

linux - fotos - fslint



¿Cómo encontrar archivos duplicados con el mismo nombre pero en diferentes casos que existen en el mismo directorio en Linux? (11)

¿Cómo puedo devolver una lista de archivos que se llaman duplicados, es decir, tienen el mismo nombre pero en diferentes casos que existen en el mismo directorio ?

No me importa el contenido de los archivos. Solo necesito saber la ubicación y el nombre de cualquier archivo que tenga un duplicado del mismo nombre.

Ejemplo de duplicados:

/www/images/taxi.jpg /www/images/Taxi.jpg

Idealmente, necesito buscar todos los archivos recursivamente desde un directorio base. En el ejemplo anterior, fue /www/


Creo

ls | sort -f | uniq -i -d

es más simple, más rápido y dará el mismo resultado


Tratar:

ls -1 | tr ''[A-Z]'' ''[a-z]'' | sort | uniq -c | grep -v " 1 "

Simple, realmente :-) ¿No son las tuberías maravillosas bestias?

El ls -1 le da los archivos uno por línea, el tr ''[AZ]'' ''[az]'' convierte todo en mayúscula a minúscula, el sort ordena (sorprendentemente), uniq -c elimina las ocurrencias subsecuentes de líneas duplicadas mientras da usted también cuenta y, finalmente, grep -v " 1 " elimina aquellas líneas donde el conteo fue uno.

Cuando ejecuto esto en un directorio con un "duplicado" (copié qq en qQ ), obtengo:

2 qq

Para la versión "este directorio y cada subdirectorio", simplemente reemplace ls -1 con find . o find DIRNAME si desea un punto de inicio de directorio específico ( DIRNAME es el nombre del directorio que desea usar).

Esto vuelve (para mí):

2 ./.gconf/system/gstreamer/0.10/audio/profiles/mp3 2 ./.gconf/system/gstreamer/0.10/audio/profiles/mp3/%gconf.xml 2 ./.gnome2/accels/blackjack 2 ./qq

que son causados ​​por:

pax> ls -1d .gnome2/accels/[bB]* .gconf/system/gstreamer/0.10/audio/profiles/[mM]* [qQ]? .gconf/system/gstreamer/0.10/audio/profiles/mp3 .gconf/system/gstreamer/0.10/audio/profiles/MP3 .gnome2/accels/blackjack .gnome2/accels/Blackjack qq qQ

Actualizar:

En realidad, en una mayor reflexión, el tr minúscula todos los componentes de la ruta para que ambos

/a/b/c /a/B/c

se considerarán duplicados aunque estén en directorios diferentes .

Si solo quiere duplicados dentro de un solo directorio para mostrar como una coincidencia, puede usar el (bastante monstruoso):

perl -ne '' chomp; @flds = split (////); $lstf = $f[-1]; $lstf =~ tr/A-Z/a-z/; for ($i =0; $i ne $#flds; $i++) { print "$f[$i]/"; }; print "$x/n";''

en lugar de:

tr ''[A-Z]'' ''[a-z]''

Lo que hace es solo minúsculas de la porción final de la ruta en lugar de todo. Además, si solo desea archivos regulares (sin directorios, FIFOs, etc.), use find -type f para restringir lo que se devuelve.


Esta es una pequeña y agradable aplicación de línea de comandos llamada findsn que obtienes si compilas fslint que el paquete deb no incluye.

encontrará cualquier archivo con el mismo nombre, y es muy rápido y puede manejar diferentes casos.

/findsn --help find (files) with duplicate or conflicting names. Usage: findsn [-A -c -C] [[-r] [-f] paths(s) ...]

Si no se proporcionan argumentos, se busca en $ PATH cualquier archivo redundante o conflictivo.

-A reports all aliases (soft and hard links) to files. If no path(s) specified then the $PATH is searched.

Si solo se especificaron las rutas, se verifican los archivos duplicados nombrados. Puede calificar esto con -C para ignorar el caso en esta búsqueda. Calificar con -c es más restrictivo que solo los archivos (o directorios) en el mismo directorio cuyos nombres difieren solo en caso de que se denuncien. IE -c marcará los archivos y directorios que entrarán en conflicto si se transfieren a un sistema de archivos que no distingue entre mayúsculas y minúsculas. Observe si se especificó -c o -C y no se especificó ninguna ruta en la que se asume el directorio actual.


Siguiendo con la respuesta de mpez0, para detectar recursivamente simplemente reemplaza "ls" por "find". El único problema que veo con esto es que si este es un directorio que está duplicando, entonces tiene 1 entrada para cada archivo en este directorio. Se requiere algo del cerebro humano para tratar el resultado de esto.

Pero de todos modos, no estás eliminando automáticamente estos archivos, ¿o sí?

find . | sort -f | uniq -i -d


Aquí hay un script que funcionó para mí (yo no soy el autor). el original y la discusión se pueden encontrar aquí: http://www.daemonforums.org/showthread.php?t=4661

#! /bin/sh # find duplicated files in directory tree # comparing by file NAME, SIZE or MD5 checksum # -------------------------------------------- # LICENSE(s): BSD / CDDL # -------------------------------------------- # vermaden [AT] interia [DOT] pl # http://strony.toya.net.pl/~vermaden/links.htm __usage() { echo "usage: $( basename ${0} ) OPTION DIRECTORY" echo " OPTIONS: -n check by name (fast)" echo " -s check by size (medium)" echo " -m check by md5 (slow)" echo " -N same as ''-n'' but with delete instructions printed" echo " -S same as ''-s'' but with delete instructions printed" echo " -M same as ''-m'' but with delete instructions printed" echo " EXAMPLE: $( basename ${0} ) -s /mnt" exit 1 } __prefix() { case $( id -u ) in (0) PREFIX="rm -rf" ;; (*) case $( uname ) in (SunOS) PREFIX="pfexec rm -rf" ;; (*) PREFIX="sudo rm -rf" ;; esac ;; esac } __crossplatform() { case $( uname ) in (FreeBSD) MD5="md5 -r" STAT="stat -f %z" ;; (Linux) MD5="md5sum" STAT="stat -c %s" ;; (SunOS) echo "INFO: supported systems: FreeBSD Linux" echo echo "Porting to Solaris/OpenSolaris" echo " -- provide values for MD5/STAT in ''$( basename ${0} ):__crossplatform()''" echo " -- use digest(1) instead for md5 sum calculation" echo " $ digest -a md5 file" echo " -- pfexec(1) is already used in ''$( basename ${0} ):__prefix()''" echo exit 1 (*) echo "INFO: supported systems: FreeBSD Linux" exit 1 ;; esac } __md5() { __crossplatform :> ${DUPLICATES_FILE} DATA=$( find "${1}" -type f -exec ${MD5} {} '';'' | sort -n ) echo "${DATA}" / | awk ''{print $1}'' / | uniq -c / | while read LINE do COUNT=$( echo ${LINE} | awk ''{print $1}'' ) [ ${COUNT} -eq 1 ] && continue SUM=$( echo ${LINE} | awk ''{print $2}'' ) echo "${DATA}" | grep ${SUM} >> ${DUPLICATES_FILE} done echo "${DATA}" / | awk ''{print $1}'' / | sort -n / | uniq -c / | while read LINE do COUNT=$( echo ${LINE} | awk ''{print $1}'' ) [ ${COUNT} -eq 1 ] && continue SUM=$( echo ${LINE} | awk ''{print $2}'' ) echo "count: ${COUNT} | md5: ${SUM}" grep ${SUM} ${DUPLICATES_FILE} / | cut -d '' '' -f 2-10000 2> /dev/null / | while read LINE do if [ -n "${PREFIX}" ] then echo " ${PREFIX} /"${LINE}/"" else echo " ${LINE}" fi done echo done rm -rf ${DUPLICATES_FILE} } __size() { __crossplatform find "${1}" -type f -exec ${STAT} {} '';'' / | sort -n / | uniq -c / | while read LINE do COUNT=$( echo ${LINE} | awk ''{print $1}'' ) [ ${COUNT} -eq 1 ] && continue SIZE=$( echo ${LINE} | awk ''{print $2}'' ) SIZE_KB=$( echo ${SIZE} / 1024 | bc ) echo "count: ${COUNT} | size: ${SIZE_KB}KB (${SIZE} bytes)" if [ -n "${PREFIX}" ] then find ${1} -type f -size ${SIZE}c -exec echo " ${PREFIX} /"{}/"" '';'' else # find ${1} -type f -size ${SIZE}c -exec echo " {} " '';'' -exec du -h " {}" '';'' find ${1} -type f -size ${SIZE}c -exec echo " {} " '';'' fi echo done } __file() { __crossplatform find "${1}" -type f / | xargs -n 1 basename 2> /dev/null / | tr ''[A-Z]'' ''[a-z]'' / | sort -n / | uniq -c / | sort -n -r / | while read LINE do COUNT=$( echo ${LINE} | awk ''{print $1}'' ) [ ${COUNT} -eq 1 ] && break FILE=$( echo ${LINE} | cut -d '' '' -f 2-10000 2> /dev/null ) echo "count: ${COUNT} | file: ${FILE}" FILE=$( echo ${FILE} | sed -e s/''/[''/''///[''/g -e s/''/]''/''///]''/g ) if [ -n "${PREFIX}" ] then find ${1} -iname "${FILE}" -exec echo " ${PREFIX} /"{}/"" '';'' else find ${1} -iname "${FILE}" -exec echo " {}" '';'' fi echo done } # main() [ ${#} -ne 2 ] && __usage [ ! -d "${2}" ] && __usage DUPLICATES_FILE="/tmp/$( basename ${0} )_DUPLICATES_FILE.tmp" case ${1} in (-n) __file "${2}" ;; (-m) __md5 "${2}" ;; (-s) __size "${2}" ;; (-N) __prefix; __file "${2}" ;; (-M) __prefix; __md5 "${2}" ;; (-S) __prefix; __size "${2}" ;; (*) __usage ;; esac

Si el comando find no funciona para usted, puede que tenga que cambiarlo. Por ejemplo

OLD : find "${1}" -type f | xargs -n 1 basename NEW : find "${1}" -type f -printf "%f/n"


Un poco tarde para esto, pero aquí está la versión que fui con:

find . -type f | awk -F/ ''{print $NF}'' | sort -f | uniq -i -d

Aquí estamos usando:

  1. find - encuentra todos los archivos bajo el directorio actual
  2. awk - elimina la parte de la ruta del archivo del nombre de archivo
  3. sort - ordenar caso insensiblemente
  4. uniq - encuentra a los engañados de lo que lo hace a través de la tubería

(Inspirado por la respuesta @ mpez0, y @SimonDowdles comenta en @paxdiablo answer.)


La otra respuesta es genial, pero en lugar de la secuencia de comandos perl "bastante monstruosa" sugiero

perl -pe ''s!([^/]+)$!lc $1!e''

Que minúscula solo el nombre del archivo parte de la ruta.

Edición 1: De hecho, todo el problema se puede resolver con:

find . | perl -ne ''s!([^/]+)$!lc $1!e; print if 1 == $seen{$_}++''

Edición 3: Encontré una solución usando sed, sort y uniq que también imprimirá los duplicados, pero solo funciona si no hay espacios en blanco en los nombres de archivo:

find . |sed ''s,/(.*/)//(.*/)$,/1//2/t/1//L/2,''|sort|uniq -D -f 1|cut -f 1

Edit 2: Y aquí hay un script más largo que imprimirá los nombres, toma una lista de rutas en stdin, como se da por find . No tan elegante, pero aún así:

#!/usr/bin/perl -w use strict; use warnings; my %dup_series_per_dir; while (<>) { my ($dir, $file) = m!(.*/)?([^/]+?)$!; push @{$dup_series_per_dir{$dir||''./''}{lc $file}}, $file; } for my $dir (sort keys %dup_series_per_dir) { my @all_dup_series_in_dir = grep { @{$_} > 1 } values %{$dup_series_per_dir{$dir}}; for my $one_dup_series (@all_dup_series_in_dir) { print "$dir/{" . join('','', sort @{$one_dup_series}) . "}/n"; } }


Acabo de usar fdupes en CentOS para limpiar un montón de archivos duplicados ...

yum install fdupes


Aquí hay un ejemplo de cómo encontrar todos los archivos jar duplicados:

find . -type f -printf "%f/n" -name "*.jar" | sort -f | uniq -i -d

Reemplace *.jar con el tipo de archivo duplicado que esté buscando.


Puede verificar duplicados en un directorio determinado con GNU awk:

gawk ''BEGINFILE {if ((seen[tolower(FILENAME)]++)) print FILENAME; nextfile}'' *

Esto usa BEGINFILE para realizar alguna acción antes de continuar y leer un archivo. En este caso, realiza un seguimiento de los nombres que han aparecido en una matriz seen[] cuyos índices son los nombres de los archivos en minúsculas.

Si ya apareció un nombre, sin importar su caso, lo imprime. De lo contrario, simplemente salta al siguiente archivo.

Vea un ejemplo:

$ tree . ├── bye.txt ├── hello.txt ├── helLo.txt ├── yeah.txt └── YEAH.txt 0 directories, 5 files $ gawk ''BEGINFILE {if ((a[tolower(FILENAME)]++)) print FILENAME; nextfile}'' * helLo.txt YEAH.txt


Puedes usar:

find -type f -exec readlink -m {} /; | gawk ''BEGIN{FS="/";OFS="/"}{$NF=tolower($NF);print}'' | uniq -c

Dónde:

  • find -type f
    recursion print all full path.

  • -exec readlink -m {} /;
    obtener la ruta absoluta del archivo

  • gawk ''BEGIN{FS="/";OFS="/"}{$NF=tolower($NF);print}''
    reemplace todos los nombres de archivo a minúsculas

  • uniq -c
    la ruta es única, -c muestra el recuento de duplicados.