Найти дубликаты по столбцу в файле

Найти дубликаты по столбцу в файле

У меня есть входной файл, содержащий пути к файлам и их md5sum, разделенные точкой с запятой и отсортированные по хэшам 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

Я хотел бы знать, как можно найти дубликаты на основе хеша и вывести их, чтобы вывод для приведенного выше ввода выглядел следующим образом:

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

Я пробовал uniq, но не смог найти, как изменить разделитель полей с пробелов на точки с запятой (некоторые пути к файлам могут содержать пробелы)

решение1

Если ваши пути не содержат пробелов или точек с запятой, просто замените точки с запятой на пробелы.

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

Если ваши пути содержат пробелы, но не содержат табуляций или точек с запятой, вы можете сделать по сути то же самое, но временно превратить пробелы в точки с запятой и использовать табуляцию в качестве разделителя полей.

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

Если вы не хотите делать никаких предположений относительно имен файлов (кроме отсутствия в них новых строк), вы можете поручить эту работу awk.

awk -F ';' '{
    if ($NF == current) {
        if (first != "") print first;
        first = "";
        print;
    } else {
        first = $0;
        current = $NF;
    }
}'

решение2

Возможным решением может быть использование следующего awk:

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

Недостаток в том, что файл читается дважды. В первом проходе мы подсчитываем и сохраняем повторения в массиве, а во втором проходе печатаем строку, если счетчик больше 1.

решение3

Довольно просто perl(для бонусных баллов - вы md5sumтоже можете это сделать).

Но что-то вроде этого:

#!/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;
}

Примечание <>- это магический дескриптор файла. Он принимает данные, переданные в скрипт через STDINили из файлов в командной строке./myscript.pl file_containing_data

решение4

Среди более умных решений вот грубая сила "однострочника", которая cutвытаскивает md5sum, прогоняет ее, uniq -cчтобы получить счетчики, использует awkдля удаления действительно уникальных значений, затем передает оставшиеся md5sums через forцикл к grepсоответствующим значениям из исходного файла. Конечно, не так элегантно, как решение Жиля all-awk, и также имеет недостаток, заключающийся в двойном чтении входного файла.

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

Я добавил дополнительные дубликаты в ваш пример входного файла:

/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

к которому приведенный выше цикл приводит:

/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

Связанный контент