Я также добавил бы, что, чтобы успешно найти (и удалить) точные дубликаты файла, необходимо сравнить файлы хешем:
#!/bin/sh -eu
find "${1:-.}" -type f ! -empty -print0 | xargs -0 md5 -r | \
awk '$1 in a{sub("^.{33}","");printf "%s\0",$0}a[$1]+=1{}' | \
xargs -0 rm -v --
Сохраните это как deldupes.sh
и выполненный это дающий dirname как 1-й параметр (иначе $PWD
использовался бы).
Протестированный на OS X, работы долгое время whitespaced имена файлов.
Я обнаружил, что сортировка - это самый быстрый инструмент uniq, как показано здесь -> Самый быстрый способ удалить дубликаты в большом списке слов?
Я просто хотел отметить, что gnu uniq
кажется ужасно медленным, даже в отсортированном списке.
Я только что попытался получить список префиксов каталогов из списка отсортированных имен файлов:
$ pv all_files | cut -d '/' -f 1,2,3,4 | uniq > all_prefixes
36.7GiB 0:07:41 [81.4MiB/s]
$ pv all_files | cut -d '/' -f 1,2,3,4 | sort -u > all_prefixes2
36.7GiB 0:03:14 [ 193MiB/s]
$ pv all_files | cut -d '/' -f 1,2,3,4 | awk '!x[$0]++' > all_prefixes3
36.7GiB 0:02:18 [ 270MiB/s]
sort -u кажется в два раза быстрее, чем uniq, и это при чтении sort со стандартного ввода и записи на стандартный вывод, поэтому я пока не вижу параллелизма. Я понятия не имею, почему uniq должен быть намного медленнее, чем sort, ведь ему не нужно сортировать список...
Вывод этой команды очень мал (много дубликатов ), всего 264kb и сортировка завершается сразу после выполнения pv.
Те же скорости остаются, если вы измените порядок команд, мой поток здесь ограничен процессорным временем, а не доступом к диску и кешем (У меня только 8 ГБ ОЗУ, и мой своп не используется)
Я запускаю это на машине с Fedora 31 с помощью gnu coreutils sort и uniq и gnu awk; установлен локаль en _US.UTF -8
ОБНОВЛЕНИЕ , поскольку это меня немного заинтриговало, я провел еще несколько тестов, давайте уберем отрезанную часть,и убедитесь, что файл хорошо отсортирован
cat all_files | cut -d '/' -f 1,2,3,4 | sort -T. > test
Это занимает 8,4 минуты. test теперь весит 7,9 ГБ
Давайте запустим эти инструменты в файле, а не в конвейере, это позволит этим инструментам выполнить дополнительную оптимизацию, например, сортировка будет многопоточной. а также с более быстрого ssd.
Вы можете не заметить, что эта сортировка также занимает много памяти, так как она делает хитрые трюки с временными файлами в /tmp, которые могут быть tmpfs и будут находиться в вашей оперативной памяти. (Попробуйте отсортировать файл больше, чем /tmp, вы столкнетесь с проблемами свободного места, поэтому мне нужен -T. флаг в приведенной выше команде)
$ time sort -u test > /dev/null
339.24user 3.54system 1:28.87elapsed 385%CPU (0avgtext+0avgdata 2365856maxresident)k
9555544inputs+0outputs (0major+591298minor)pagefaults 0swaps
$ time awk '!x[$0]++' test > /dev/null
51.15user 1.55system 0:52.94elapsed 99%CPU (0avgtext+0avgdata 10976maxresident)k
0inputs+0outputs (0major+1923minor)pagefaults 0swaps
$ time uniq test > /dev/null
421.89user 2.76system 7:06.63elapsed 99%CPU (0avgtext+0avgdata 1980maxresident)k
52712inputs+0outputs (0major+79minor)pagefaults 0swaps
Похоже, ваше решение на awk самое быстрое из этих трех и на самом деле использует наименьшее количество памяти
обновление2 и теперь с более простой локалью
$ export LC_ALL=c
$ time sort -u test > /dev/null 1.2m ? Tue Apr 21 17:09:22 2020
119.18user 3.64system 0:38.24elapsed 321%CPU (0avgtext+0avgdata 2013472maxresident)k
$ time awk '!x[$0]++' test > /dev/null 1161ms ? Tue Apr 21 17:07:31 2020
67.23user 2.50system 1:10.16elapsed 99%CPU (0avgtext+0avgdata 10480maxresident)k
7187520inputs+0outputs (0major+1912minor)pagefaults 0swaps
$ time uniq test > /dev/null
22.05user 2.02system 0:24.24elapsed 99%CPU (0avgtext+0avgdata 1488maxresident)k
2959648inputs+0outputs (1major+72minor)pagefaults 0swaps
На этот раз uniq выигрывает гонку ... Как намекает Стефан Шазеля в комментариях, установка языкового стандарта C делает сортировку и уникальность намного быстрее!