Команда uniq не работает должным образом?
Итак, я проверяю md5
хеш моих файлов с этим как мой вывод:
657cf4512a77bf47c39a0482be8e41e0 ./dupes2.txt
657cf4512a77bf47c39a0482be8e41e0 ./dupes.txt
8d60a927ce0f411ec94ac26a4785f749 ./derpina.txt
15f63928b8a1d5337137c38b5d66eed3 ./foo.txt
8d60a927ce0f411ec94ac26a4785f749 ./derp.txt
Однако после запуска find . -type f -exec md5sum '{}' ';' | uniq -w 33
чтобы найти уникальные хеши, я получаю это:
657cf4512a77bf47c39a0482be8e41e0 ./dupes2.txt
8d60a927ce0f411ec94ac26a4785f749 ./derpina.txt
15f63928b8a1d5337137c38b5d66eed3 ./foo.txt
8d60a927ce0f411ec94ac26a4785f749 ./derp.txt
Насколько я понимаю, только один из derpina.txt
или же derp.txt
должен появиться, так как их хеши совпадают. Я что-то пропустил? Может кто-нибудь просветить меня, почему это выводит, как это?
4 ответа
Вам нужно использовать sort
до uniq
:
find . -type f -exec md5sum {} ';' | sort | uniq -w 33
uniq
удаляет только повторяющиеся строки Он не переупорядочивает строки в поисках повторов. sort
делает эту часть.
Это задокументировано в man uniq
:
Примечание: "uniq" не обнаруживает повторяющиеся строки, если они не являются смежными. Вы можете сначала отсортировать ввод или использовать
sort -u' without
уник.
Вход для uniq
нужно отсортировать. Так что для примера,
find . -type f -exec md5sum '{}' ';' | sort | uniq -w 33
должно сработать. -w
(--check-chars=N
) делает строки уникальными только в отношении первого столбца; Эта опция работает для этого случая. но возможности указать соответствующие части линии для uniq
ограничены. Например, нет опций для указания работы с некоторыми столбцами 3 и 5, игнорируя столбец 4.
Команда sort
имеет опцию для уникальных строк вывода, а строки уникальны в отношении ключей, используемых для сортировки. Это означает, что мы можем использовать мощный синтаксис ключа sort
определить, в какой части строки должны быть уникальными.
Например,
find . -type f -exec md5sum '{}' ';' | sort -k 1,1 -u
дает точно такой же результат, но sort
часть является более гибкой для других целей.
Команда не будет работать, если ввод не буферизован (например, с помощью
sort
) или повторяющиеся строки находятся рядом друг с другом. Итак, найдите ниже несколько решений.
АВК
Вот синтаксис для
awk
:
command | awk '!a[$0]++{print}'
Для многократного использования вы можете определить следующий псевдоним оболочки:
alias unicat='awk "!a[\$0]++{print}"'
затем запустите: .
Параллельный синтаксис (для более быстрого синтаксического анализа):
command | time parallel --block 100M --pipe awk '!a[\$0]++{print}'
Тестовая команда (отфильтровано 100 строк из 200):
echo | pee "seq 1 100" "seq 1 100" | awk '!a[$0]++{print}' | wc -l
Перл
Попробуйте следующий Perl-скрипт:
command | perl -e 'while(<>){if(!$s{$_}){print $_;$|=1;$s{$_}=1;}}'
Синтаксис псевдонима оболочки для повторного использования:
alias unicat='perl -e '\''while(<>){if(!$s{$_}){print $_;$|=1;$s{$_}=1;}}'\'''
затем запустите:
command | unicat
.
В качестве альтернативы вы также можете использовать karrick's
unique
написан на Go (используется тот же подход, что и выше, но он намного быстрее и использует меньше памяти, чем решения Perl/AWK):
Применение:
command | unique
Минусы: при обработке огромных данных используется много памяти, так как каждый элемент хешируется и добавляется в массив.
Обходной путь может заключаться в том, чтобы иметь короткоживущие экземпляры для определенного размера блока (если допустимо несколько дубликатов), например
command | parallel --block 100M -j 1 --pipe unique
или используя
split
(10M на блок), например
command | split -b 10M --filter="unique"
Использовать
quniq
утилита для удаления дубликатов. Это работает лучше, чем
uniq
, так как он буферизует входные строки.
- Страница проекта: https://github.com/syucream/quuniq
- Установить:
go install github.com/syucream/quniq@latest
Минусы: Кажется, что он застрял до конца трубы.
Если вы ищете более быстрое решение для сортировки, а затем удаления дубликатов, используйте
huniq
.
- Страница проекта: https://github.com/koraa/huniq
- Установить:
cargo install huniq
Еще похожие проекты:
- https://github.com/mitsutoshi/uni (написано на Rust)
- https://github.com/whitfin/runiq (написано на Rust)
- https://github.com/miolini/uniqbloom (написано на Go, с использованием фильтра Блума)
Или вы можете установить killdupes, мою программу, чтобы уничтожить все, что есть!
https://github.com/batchmcnulty/killdupes
:-)