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