Localiza arquivos que possuem uma duplicata confirmada no mesmo diretório recursivamente

3

Digamos que eu tenha a seguinte estrutura de diretório:

root
 |-- dirA
     |-- file.jpg
     |-- file-001.jpg <-- dup
     |-- file2.jpg
     |-- file3.jpg
 |-- dirB
     |-- fileA.jpg
     |-- fileA_ios.jpg <-- dup
     |-- fileB.jpg
     |-- fileC.jpg
 |-- dirC
     |-- fileX.jpg
     |-- fileX_ios.jpg <-- dup
     |-- fileX-001.jpg <-- dup
     |-- fileY.jpg
     |-- fileZ.jpg

Então, dada uma pasta raiz, como posso encontrar dups que possuem nomes idênticos (diferindo apenas por um sufixo) recursivamente?

O nome pode ser qualquer string e não necessariamente file... . Os sufixos podem ser 001, 002, 003 e assim por diante. Mas é seguro assumir que haverá um padrão numérico de 3 dígitos e _ios literalmente (para correspondência regex).

Meu linux foo não é muito bom.

    
por Mrchief 27.11.2014 / 21:28

3 respostas

2

É um pouco longo, mas é uma única linha de comando. Isso examina o conteúdo dos arquivos e compara-os usando um hash criptográfico ( md5sum ).

find . -type f -exec md5sum {} + | sort | sed 's/  */!/1' | awk -F\| 'BEGIN{first=1}{if($1==lastid){if(first){first=0;print lastid, lastfile}print$1, $2} else first=1; lastid=$1;lastfile=$2}'

Como eu disse, isso é um pouco longo ...

O find executa md5sum em todos os arquivos na árvore de diretórios atual. Então a saída é sort d pelo hash md5. Como o espaço em branco pode estar nos nomes de arquivos, o sed altera o primeiro separador de campo (dois espaços) para um canal vertical (muito improvável que esteja em um nome de arquivo).

O último comando awk rastreia três variáveis: lastid = o hash md5 da entrada anterior, lastfile = o nome do arquivo da entrada anterior e first = lastid foi visto pela primeira vez.

A saída inclui o hash para que você possa ver quais arquivos são duplicados entre si.

Isso não indica se os arquivos são hard links (mesmo inode, nome diferente); só vai comparar o conteúdo.

Atualização: corrigida com base no nome básico do arquivo.

find . -type f -print | sed 's!.*/\(.*\)\.[^.]*$!|&!' | awk -F\| '{i=indices[$1]++;found[$1,i]=$2}END{for(bname in indices){if(indices[bname]>1){for(i=0;i<indices[bname];i++){print found[bname,i]}}}}'

Aqui, o find apenas lista os nomes dos arquivos, o sed toma o componente de nome de base do nome do caminho e cria uma tabela de dois campos com o nome da base e o nome completo do caminho. O awk , em seguida, cria uma tabela ("found") dos nomes de caminho vistos, indexados pelo nome da base e o número do item; o array "indices" registra quantos desses nomes de base foram vistos. A cláusula "END" imprime os nomes de referência duplicados encontrados.

    
por 29.11.2014 / 19:18
0

Você pode considerar programas especificamente destinados à pesquisa de arquivos duplicados, em vez de confiar no nome, por exemplo, fdupes ou fslint .

    
por 27.11.2014 / 22:43
0

Crie uma estrutura de diretórios

mkdir dir{A,B,C}
touch dirA/file{,-001,2,3}.jpg
touch dirB/file{A,A_ios,B,C}.jpg
touch dirC/file{X,X_ios,X-001,Y,Z}.jpg

Mostrar multiplicidade de arquivos duplicados

find . -name '*.jpg' -type f |sed 's/\(.*\/\(file.\).*\(.jpg\)\)//' |sort |uniq -c|grep -v 1 

Retorna

2 fileA
3 fileX

    
por 28.11.2014 / 17:44