Encontre duplicatas por coluna em um arquivo

3

Eu tenho um arquivo de entrada contendo caminhos de arquivo e seu md5sum, separados por ponto e vírgula e classificados por hashes md5:

/media/LaCie/Images/recup2/recup_dir.1/f1295328.jpg;0080ececd3da8533f5d11e449cf73287
/media/LaCie/Documents/pics/897_FUJI/DSCF7042.JPG;0081cd15705f0c541995e13ad3e405b8
/media/LaCie/Documents/Pictures/124_FUJI/DSCF4729.JPG;00829232ae6b181654ee87ff32d161f8
/media/LaCie/Images/Trashes/501/IMG_0651.JPG;00833c74523d5361641af863f5d92387
/media/LaCie/Images/2009-09/IMG_0651.JPG;00833c74523d5361641af863f5d92387

Gostaria de saber como encontrar duplicatas com base no hash e imprimi-las, para que a saída da entrada acima seja assim:

/media/LaCie/Images/Trashes/501/IMG_0651.JPG;00833c74523d5361641af863f5d92387
/media/LaCie/Images/2009-09/IMG_0651.JPG;00833c74523d5361641af863f5d92387

Eu tentei uniq , mas não consegui encontrar como alterar seu separador de campo de espaços para ponto e vírgula (alguns caminhos de arquivo podem ter espaços neles)

    
por l0r3nz4cc10 14.02.2016 / 16:29

4 respostas

3

Se seus caminhos não contiverem espaços ou pontos-e-vírgulas, basta transformar os pontos-e-vírgulas em espaços.

tr ';' ' ' | uniq -f 1 -d | tr ' ' ';'

Se seus caminhos contiverem espaços, mas não guias ou ponto-e-vírgulas, você poderá fazer basicamente a mesma coisa, mas transformar temporariamente os espaços em ponto e vírgula e usar uma guia como o separador de campos.

tr '; ' '\t;' | uniq -f 1 -d | tr '\t;' '; '

Se você não quiser fazer suposições sobre os nomes dos arquivos (além de não conter novas linhas), você pode fazer o awk fazer o trabalho.

awk -F ';' '{
    if ($NF == current) {
        if (first != "") print first;
        first = "";
        print;
    } else {
        first = $0;
        current = $NF;
    }
}'
    
por 14.02.2016 / 23:10
2

Possível solução pode estar usando o seguinte awk :

awk -F";" 'FNR == NR { x[$2]++; next; } { if ($2 in x && x[$2] > 1) print; }' file file

Advertência com isto é que o arquivo é lido duas vezes. No primeiro passo nós contamos e armazenamos repetições em array e no segundo passo nós imprimimos row se o contador for maior que 1.

    
por 14.02.2016 / 20:30
0

Bastante fácil com perl (para pontos de bônus - você também pode fazer o md5sum ).

Mas algo assim:

#!/usr/bin/env perl
use strict;
use warnings;

my %file_md5; 

while ( <> ){
   chomp; 
   my ( $filename, $hash ) = split /;/; 
   if ( $file_md5{$hash} ) { 
       print "$filename has the same md5sum as $file_md5{$hash}\n";
   }
   $file_md5{$hash} = $filename;
}

Note que <> é o filehandle mágico. Os dados são enviados para o script por meio de STDIN ou de arquivos na linha de comando ./myscript.pl file_containing_data

    
por 15.02.2016 / 17:32
0

Entre as soluções mais inteligentes, aqui está uma força bruta "one-liner" que cut s sai do md5sum, executa uniq -c para obter as contagens, usa awk para remover os valores realmente únicos, em seguida, passa os md5sums restantes por meio de um loop for para grep dos valores correspondentes do arquivo original. Certamente não é tão elegante quanto a solução totalmente desajeitada de Gilles, e também tem a queda de ler o arquivo de entrada duas vezes.

for md5 in $(cut -d\; -f2 inputfile-here | uniq -c | awk '$1 > 1 { print $2 }')
do 
  grep ";$md5\$" inputfile-here
  echo  ## gratuitous blank line to separate the duplicates
done

Eu adicionei duplicações extras ao seu arquivo de entrada de amostra:

/media/LaCie/Images/recup2/recup_dir.1/f1295328.jpg;0080ececd3da8533f5d11e449cf73287
/media/LaCie/Documents/pics/897_FUJI/DSCF7042.JPG;0081cd15705f0c541995e13ad3e405b8
/media/LaCie/Documents/Pictures/124_FUJI/DSCF4729.JPG;00829232ae6b181654ee87ff32d161f8
/media/LaCie/Documents/Pictures/124_FUJI/DSCF4729-1.JPG;00829232ae6b181654ee87ff32d161f8
/media/LaCie/Documents/Pictures/124_FUJI/DSCF4729-2.JPG;00829232ae6b181654ee87ff32d161f8
/media/LaCie/Images/Trashes/501/IMG_0651.JPG;00833c74523d5361641af863f5d92387
/media/LaCie/Images/2009-09/IMG_0651.JPG;00833c74523d5361641af863f5d92387

para o qual o loop acima produz:

/media/LaCie/Documents/Pictures/124_FUJI/DSCF4729.JPG;00829232ae6b181654ee87ff32d161f8
/media/LaCie/Documents/Pictures/124_FUJI/DSCF4729-1.JPG;00829232ae6b181654ee87ff32d161f8
/media/LaCie/Documents/Pictures/124_FUJI/DSCF4729-2.JPG;00829232ae6b181654ee87ff32d161f8

/media/LaCie/Images/Trashes/501/IMG_0651.JPG;00833c74523d5361641af863f5d92387
/media/LaCie/Images/2009-09/IMG_0651.JPG;00833c74523d5361641af863f5d92387
    
por 15.02.2016 / 17:52