É 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.