Счетчик уникальных файлов в каталоге

Кажется, я нашел причину зависания ядра. Последовательный драйвер atmel _отключает передатчик UART, когда init закрывает консольное устройство (/dev/console ). Затем следующий printk из ядра зависает, ожидая, пока THR не опустеет. Эта ошибка была исправлена ​​в ветке upstream 4.4 -at91 (https://github.com/linux4sam/linux-at91/commit/0a1757cfa5ba3b46f6ee7a74ddb7a5c0bd5d7c2f)

.

5
23.10.2019, 15:25
4 ответа

Немного расширив решение @Isaac....

Предполагая синтаксис bashи учитывая:

$ find test -type f
test/AA
test/A
test/C
test/CC
test/B
test/D

где файлы A и AA идентичны, как C и CC;

Это более эффективный конвейер команд.:

$ find test -maxdepth 1 -type f -exec bash -c "md5sum < {}" \; |
    sort -k1,1 |
    uniq --count
      2 102f2ac1c3266e03728476a790bd9c11  -
      1 4c33d7f68620b7b137c0ca3385cb6597  -
      1 88178a003e2305475e754a7ec21d137d  -
      2 c7a739d5538cf472c8e87310922fc86c  -

Оставшаяся проблема заключается в том, что хэши md5 не говорят вам, какие файлы являются A, B, C или D. Это можно решить, хотя это немного неудобно.

Во-первых, переместите свои файлы в подкаталог или переместите свой PWD на один каталог выше, если это более удобно. В моем примере я работаю в ., а файлы находятся в test/.

Я предлагаю вам определить по одному файлу каждого из четырех типов и скопировать их в файл A, B, C и D (и далее, если вам нужно, вплоть до Z):

$ cp -p test/file1002./A
...
$ cp -p test/file93002./N

и т. д. Теперь мы можем построить хэш-таблицу, которая определяет хэши md5 каждого уникального выходного файла A -Z:

$ for file in [A-Z]; do 
      printf "s/%s/%s/\n" "$(md5sum < $file )" "$file"; 
done
s/102f2ac1c3266e03728476a790bd9c11  -/A/
s/4c33d7f68620b7b137c0ca3385cb6597  -/B/
s/c7a739d5538cf472c8e87310922fc86c  -/C/
s/88178a003e2305475e754a7ec21d137d  -/D/

Обратите внимание, что хеш-таблица имеет синтаксис sed. Вот почему:

Запустим тот же конвейер find... md5sumвыше:

$ find test -maxdepth 1 -type f -exec bash -c "md5sum < {}" \; |
    sort -k1,1 |
    uniq --count

... и передать его через процесс sed, который использует приведенную выше хеш-таблицу для замены хеш-значений именами файлов-прототипов. Команда sedсама по себе будет:

sed -f <(
    for file in [A-Z]; do 
        printf "s/%s/%s/\n" "$(md5sum < "$file")" "$file"; 
    done
)

Чтобы соединить все вместе:

$ find test -maxdepth 1 -type f -exec bash -c "md5sum < {}" \; |
    sort -k1,1 |
    uniq --count |
    sed -f <(
        for file in [A-Z]; do 
            printf "s/%s/%s/\n" "$(md5sum < "$file")" "$file"; 
        done
    )
  2 A
  1 B
  1 D
  2 C

Если вы видите такой вывод:

  2 A
  1 B
  1 5efa8621f70e1cad6aba9f8f4246b383  -
  1 D
  2 C

Это означает, что в test/есть файл, значение MD5 которого не соответствует вашим файлам A -D. Другими словами, где-то существует формат выходного файла E. Как только вы найдете его (md5sum test/* | grep 5efa8621f70e1cad6aba9f8f4246b383), вы можете скопировать его в E и заново -запустить :

.
$ cp -p test/file09876./E
$ find test -maxdepth 1 -type f -exec bash -c "md5sum < {}" \; |
    sort -k1,1 |
    uniq --count |
    sed -f <(
        for file in [A-Z]; do 
            printf "s/%s/%s/\n" "$(md5sum < "$file")" "$file"; 
        done
    )
  2 A
  1 B
  1 E
  1 D
  2 C
4
27.01.2020, 20:34

Используйте хеш-карту для сбора всех уникальных файлов. Хэш зависит от содержимого, поэтому только файлы с уникальным содержимым получают запись в хеш-карте.

declare -A unique_files
for file in *; do 
    unique_files["$(md5sum "$file" | cut -d ' ' -f 1)"]="$file"
done
echo "${unique_files[@]}"
0
27.01.2020, 20:34

Для этого также можно использовать sortи uniq. В папке, где находятся файлы, введите:

find. -type f | awk '{ print "tr \\\\n @ < " $0 "; echo "}' | sh | sort | uniq --count

(Замените uniq --countна uniq -c, если не используется uniqиз GNU coreutils.)

Это должно дать вам результаты сразу. Для простоты и скорости (избегая хэшей )мы переводим новые строки в@--это может быть любой отдельный символ, не являющийся частью исходного файла.

(Это предполагает, что файлы в подпапках -, если они существуют, должны быть включены. Другое предположение состоит в том, что в файле нет символа @. Если нет, пожалуйста, прокомментируйте, и я соответствующим образом изменю команду.)

1
27.01.2020, 20:34

Я большой поклонник GNUdatamash(https://www.gnu.org/software/datamash/). Вот пример вывода смоделированного набора файлов, который я создал и запустил эту команду на:

$ md5sum * | datamash -W -s -g 1 count 2 -f
5591dadf0051bee654ea41d962bc1af0    junk1   27
9c08c31b951a1a1e0c3a38effaca5863    junk2   17
f1e5cbfade7063a0c4fa5083fd36bf1a    junk3   7

Есть 27 файлов с хешем 5591..., и один из них "junk1". (Точно так же 17 файлов, которые совпадают с "junk2", и 7 для "junk3" ).

-Wговорит использовать пробелы в качестве разделителя полей. -s -g 1говорит о сортировке и группировке по полю 1 (, которое является хешем ). countмогло быть либо полем 1, либо полем 2, не имеет значения.

-fговорит "печатать всю строку ввода". У этого есть особенность: когда вы печатаете агрегированные результаты, он печатает только полную строку для первой строки в каждой найденной группе. В данном случае это работает нормально, поскольку дает нам одно из имен файлов, участвующих в каждом наборе дубликатов -, а не все.

5
27.01.2020, 20:34

Теги

Похожие вопросы