Як отримати суму MD5 вмісту каталогу як одну суму?


171

Програма md5sum не забезпечує контрольні суми для каталогів. Я хочу отримати єдину контрольну суму MD5 на весь вміст каталогу, включаючи файли в підкаталогах. Тобто одна комбінована контрольна сума складається з усіх файлів. Чи є спосіб це зробити?

Відповіді:


186

Правильний спосіб залежить від того, чому саме ви запитуєте:

Варіант 1: Порівняйте лише дані

Якщо вам просто потрібен хеш вмісту файлу дерева, це зробить фокус:

$ find -s somedir -type f -exec md5sum {} \; | md5sum

Це спочатку підсумовує весь вміст файлу окремо, у передбачуваному порядку, потім передає цей список назв файлів та хешів MD5, щоб бути хешованим, даючи єдине значення, яке змінюється лише при зміні вмісту одного з файлів у дереві.

На жаль, find -sпрацює лише з BSD find (1), який використовується в macOS, FreeBSD, NetBSD та OpenBSD. Щоб отримати щось порівнянне в системі з GNU або SUS find (1), вам потрібно дещо потворніше:

$ find somedir -type f -exec md5sum {} \; | sort -k 2 | md5sum

Ми замінили find -sзаклик до sort. -k 2Біт говорить це , щоб пропустити через хеш MD5, тому він сортує тільки імена файлів, які знаходяться в полі 2 через кінець-лінії, по sortрозрахунками «s.

У цій версії команди є слабкість, яка полягає в тому, що вона може заплутатися, якщо у вас є імена файлів з новими рядками в них, оскільки це буде схоже на кілька рядків для sortвиклику. find -sВаріант не має цієї проблеми, так як обхід дерева і сортування відбувається в протягом однієї і тієї ж програми, find.

У будь-якому випадку сортування необхідне, щоб уникнути помилкових позитивів: найпоширеніші файлові системи Unix / Linux не підтримують списки каталогів у стабільному передбачуваному порядку. Ви можете не усвідомити це з використанням lsта таких, які мовчки сортують вміст каталогу для вас. findбез -sабо з sortвикликом буде друкувати файли в будь-якому порядку, повертаючи їх в основну файлову систему, що призведе до того, що ця команда надасть змінене хеш-значення, якщо порядок файлів, наданих їй як вхід, зміниться.

Можливо, вам знадобиться змінити md5sumкоманди на md5будь-яку іншу хеш-функцію. Якщо ви вибрали іншу хеш-функцію і вам потрібна друга форма команди для вашої системи, вам може знадобитися відповідно налаштувати sortкоманду. Ще одна пастка полягає в тому, що деякі програми зведення даних взагалі не виписують ім’я файлу, головним прикладом є стара sumпрограма Unix .

Цей метод дещо неефективний, викликаючи md5sumN + 1 раз, де N - кількість файлів у дереві, але це необхідна вартість, щоб уникнути хешування метаданих файлів та каталогів.

Варіант 2: Порівняйте дані та метадані

Якщо вам потрібно мати можливість виявити, що щось на дереві змінилося, а не лише вміст файлу, попросіть tarспакувати вміст каталогу для вас, а потім надішліть його md5sum:

$ tar -cf - somedir | md5sum

Оскільки tarтакож бачать дозволи файлів, право власності тощо, це також виявить зміни в цих речах, а не лише зміни вмісту файлу.

Цей метод значно швидший, оскільки він робить лише один прохід по дереву і запускає хеш-програму лише один раз.

Як і в findоснові вищевказаного методу, tarзбирається обробляти імена файлів у порядку, коли їх повертає файлова система. Цілком можливо, що у вашій заяві ви можете бути впевнені, що ви цього не зробите. Я можу придумати щонайменше три різних схеми використання, де це, мабуть, так і є. (Я не збираюсь їх перераховувати, тому що ми потрапляємо на не визначену територію поведінки. Тут кожна файлова система може бути різною, навіть від однієї версії ОС до іншої.)

Якщо ви виявите, що ви отримаєте помилкові позитивні результати, рекомендую перейти до цього find | cpioваріанту у відповіді Жиля .


7
Я думаю, що найкраще перейти до каталогу, який порівнюється, а не використовувати find .його find somedir. Таким чином імена файлів однакові при наданні різних специфікацій шляху; це може бути складним :-)
Аббафей

Чи слід також сортувати файли?
CMCDragonkai

@CMCDragonkai: Що ти маєш на увазі? У першому випадку ми б впорядкувати список імен файлів. У другому випадку, ми навмисно не тому , що частина підкресленого нічого в першому реченні є те , що порядок файлів в директорії змінився, так що ви не хотіли б, щоб впорядкувати нічого.
Воррен Янг

@WarrenYoung Чи можете ви пояснити трохи детальніше, чому варіант 2 не завжди кращий? Здається, це швидше, простіше і крос-платформи. У такому випадку не повинен бути варіант 1?
Робін Уінслоу

Варіант 1 альтернатива: find somedir -type f -exec sh -c "openssl dgst -sha1 -binary {} | xxd -p" \; | sort | openssl dgst -sha1ігнорувати всі назви файлів (слід працювати з новими рядками)
вітер

38

Контрольна сума повинна мати детерміноване та однозначне подання файлів як рядка. Детермінований означає, що якщо ви розмістите ті самі файли в одних і тих же місцях, ви отримаєте той самий результат. Однозначно означає, що два різних набори файлів мають різні подання.

Дані та метадані

Створення архіву, що містить файли, є хорошим початком. Це однозначне подання (очевидно, оскільки ви можете відновити файли, витягнувши архів). Він може включати метадані файлів, такі як дати та права власності. Однак це ще не зовсім правильно: архів неоднозначний, оскільки його подання залежить від порядку, в якому зберігаються файли, та, якщо застосовно, від стиснення.

Рішенням є сортування імен файлів перед їх архівуванням. Якщо назви ваших файлів не містять нових рядків, ви можете запустити їх find | sortдо списку та додати їх до архіву в цьому порядку. Не забудьте сказати архіватору не повторюватися в каталогах. Ось приклади з POSIX pax, GNU tar та cpio:

find | LC_ALL=C sort | pax -w -d | md5sum
find | LC_ALL=C sort | tar -cf - -T - --no-recursion | md5sum
find | LC_ALL=C sort | cpio -o | md5sum

Тільки назви та вміст, малотехнологічний шлях

Якщо ви хочете взяти до уваги лише дані файлу, а не метадані, ви можете створити архів, який містить лише вміст файлу, але для цього немає стандартних інструментів. Замість того, щоб включати вміст файлу, ви можете включити хеш файлів. Якщо назви файлів не містять нових рядків, а є лише звичайні файли та каталоги (немає символічних посилань або спеціальних файлів), це досить просто, але вам потрібно подбати про кілька речей:

{ export LC_ALL=C;
  find -type f -exec wc -c {} \; | sort; echo;
  find -type f -exec md5sum {} + | sort; echo;
  find . -type d | sort; find . -type d | sort | md5sum;
} | md5sum

До списку контрольних сум ми включаємо список каталогів, оскільки в іншому випадку порожні каталоги будуть невидимими. Список файлів сортується (у певній, відтворюваній мові - завдяки Peter.O за те, що нагадав мені про це). echoрозділяє дві частини (без цього ви можете зробити кілька порожніх каталогів, назва яких виглядає як md5sumвихід, який також може передаватися для звичайних файлів). Ми також включаємо перелік розмірів файлів, щоб уникнути атак з розширенням довжини .

До речі, MD5 застарілий. Якщо вона доступна, розгляньте можливість використання SHA-2 або принаймні SHA-1.

Імена та дані, що підтримують нові рядки в назвах

Ось варіант коду вище, який спирається на інструменти GNU для розділення імен файлів з нульовими байтами. Це дозволяє іменам файлів містити нові рядки. Утиліти для дайджесту GNU цитують спеціальних символів у своєму випуску, тому не буде неоднозначних нових рядків.

{ export LC_ALL=C;
  du -0ab | sort -z; # file lengths, including directories (with length 0)
  echo | tr '\n' '\000'; # separator
  find -type f -exec sha256sum {} + | sort -z; # file hashes
  echo | tr '\n' '\000'; # separator
  echo "End of hashed data."; # End of input marker
} | sha256sum

Більш надійний підхід

Ось мінімально перевірений скрипт Python, який створює хеш, що описує ієрархію файлів. Він приймає каталоги та вміст файлів до облікових записів та ігнорує символічні посилання та інші файли та повертає фатальну помилку, якщо будь-який файл неможливо прочитати.

#! /usr/bin/env python
import hashlib, hmac, os, stat, sys
## Return the hash of the contents of the specified file, as a hex string
def file_hash(name):
    f = open(name)
    h = hashlib.sha256()
    while True:
        buf = f.read(16384)
        if len(buf) == 0: break
        h.update(buf)
    f.close()
    return h.hexdigest()
## Traverse the specified path and update the hash with a description of its
## name and contents
def traverse(h, path):
    rs = os.lstat(path)
    quoted_name = repr(path)
    if stat.S_ISDIR(rs.st_mode):
        h.update('dir ' + quoted_name + '\n')
        for entry in sorted(os.listdir(path)):
            traverse(h, os.path.join(path, entry))
    elif stat.S_ISREG(rs.st_mode):
        h.update('reg ' + quoted_name + ' ')
        h.update(str(rs.st_size) + ' ')
        h.update(file_hash(path) + '\n')
    else: pass # silently symlinks and other special files
h = hashlib.sha256()
for root in sys.argv[1:]: traverse(h, root)
h.update('end\n')
print h.hexdigest()

Добре, це працює, дякую. Але чи можна це зробити без включення метаданих? Зараз мені це потрібно лише для фактичного вмісту.

Як щодо LC_ALL=C sortперевірки з різних середовищ ... (+ 1 btw)
Peter.O

Ви зробили для цього цілу програму Python? Дякую! Це справді більше, ніж я очікував. :-) У будь-якому разі я перевірю ці методи, а також новий варіант 1 від Уоррена.

Хороша відповідь. Встановлення порядку сортування за допомогою LC_ALL=Cє важливим, якщо він працює на декількох машинах та ОС.
Давор Кубраніч

Що cpio -o -означає? Чи cpio не використовує stdin / out за замовчуванням? GNU cpio 2.12 виробляєcpio: Too many arguments
Ян Тойнар

12

Погляньте на md5deep . Деякі функції md5deep, які можуть вас зацікавити:

Рекурсивна операція - md5deep здатний рекурсивно вивчити ціле дерево каталогів. Тобто обчисліть MD5 для кожного файлу в каталозі та для кожного файла у кожному підкаталозі.

Режим порівняння - md5deep може прийняти список відомих хешів і порівняти їх із набором вхідних файлів. Програма може відображати або ті вхідні файли, які відповідають списку відомих хешів, або ті, які не відповідають.

...


Приємно, але не можна змусити його працювати, мовляв .../foo: Is a directory, що дає?
Каміло Мартін

3
Сам по собі md5deep не вирішує проблему ОП, оскільки він не друкує консолідований md5sum, він просто друкує md5sum для кожного файлу в каталозі. Однак, ви можете md5sum вихід md5deep - не зовсім те, що хотів ОП, але це близько! наприклад, для поточного каталогу: md5deep -r -l -j0 . | md5sum(де -rє рекурсивним, -lозначає "використовувати відносні шляхи", щоб абсолютний шлях файлів не втручався при спробі порівняння вмісту двох каталогів, і -j0означає використовувати 1 потік для запобігання недетермінізму через до окремих md5sums, що повертаються в різних порядках).
Стіві

Як ігнорувати деякі файли / каталоги на шляху?
Сандепіан Нат

9

Якщо ваша мета полягає лише в тому, щоб знайти відмінності між двома каталогами, подумайте про використання diff.

Спробуйте це:

diff -qr dir1 dir2

Так, це теж корисно. Я думаю, ти мав на увазі dir1 dir2 у цій команді.

1
Зазвичай я не використовую графічні інтерфейси, коли я можу їх уникати, але для каталогу, що відрізняється kdiff3, це чудово, а також працює на багатьох платформах.
sinelaw

Про цю команду також повідомляються про різні файли.
Серж Стройбандт

7

Ви можете хешувати кожен файл рекурсивно, а потім хешувати отриманий текст:

> md5deep -r -l . | sort | md5sum
d43417958e47758c6405b5098f151074 *-

md5deep потрібно.


1
замість md5deepвикористання hashdeepна ubuntu 16.04, оскільки пакет md5deep - це лише перехідний макет для hashdeep.
palik

1
Я спробував hashdeep. Він виводить не тільки хеші, але і деякий заголовок, включаючи, ## Invoked from: /home/myuser/dev/який ваш поточний шлях і ## $ hashdeep -s -r -l ~/folder/. Це вдалося сортувати, тож остаточний хеш буде іншим, якщо ви зміните поточну папку чи командний рядок.
truf

3

Лише вміст файлу , крім імен файлів

Мені потрібна була версія, яка перевіряла лише імена файлів, оскільки вміст знаходиться в різних каталогах.

Ця версія (відповідь Уоррена Янга) дуже допомогла, але моя версія md5sumвиводить ім'я файлу (відносно шляху, з якого я запустив команду), і назви папок були різними, тому, хоч окремі контрольні суми файлів відповідали, остаточна контрольна сума не зробила 'т.

Щоб виправити це, у моєму випадку мені просто потрібно було викреслити ім’я файлу з кожного рядка findвиводу (виберіть лише перше слово як розділене пробілами cut):

find -s somedir -type f -exec md5sum {} \; | cut -d" " -f1 | md5sum

Вам може знадобитися сортувати контрольні суми, щоб отримати список, який можна відтворити.
eckes

3

рішення :

$ pip install checksumdir
$ checksumdir -a md5 assets/js
981ac0bc890de594a9f2f40e00f13872
$ checksumdir -a sha1 assets/js
88cd20f115e31a1e1ae381f7291d0c8cd3b92fad

працює швидше і простіше рішення, ніж баш сценаріїв.

див. документ: https://pypi.python.org/pypi/checksumdir/1.0.5


якщо у вас немає пипа вам , можливо , доведеться встановити його з допомогою Yum -y встановити пітон-піп (або д.н.ф. / кв-отримати)
DmitrySemenov

3

nix-hashвід менеджера пакетів Nix

Команда nix-хеш обчислює криптографічний хеш вмісту кожного шляху і друкує його на стандартному виході. За замовчуванням він обчислює хеш MD5, але доступні й інші хеш-алгоритми. Хеш друкується шістнадцяткою.

Хеш обчислюється через серіалізацію кожного контуру: дамп дерева файлової системи, корінням якого є шлях. Це дозволяє хеджувати каталоги та посилання, а також звичайні файли. Демпп у форматі NAR, створеному nix-store --dump. Таким чином, nix-хеш-шлях дає той самий криптографічний хеш, що і nix-store --dump path | md5sum.


2

Я використовую цей мій фрагмент для помірних обсягів :

find . -xdev -type f -print0 | LC_COLLATE=C sort -z | xargs -0 cat | md5sum -

і цей для XXXL :

find . -xdev -type f -print0 | LC_COLLATE=C sort -z | xargs -0 tail -qc100 | md5sum -


Що робить -xdevпрапор?
czerasz

Він вимагає ввести: man findта прочитати цю чудову інструкцію;)
poige

Влучне зауваження :-). -xdev Don't descend directories on other filesystems.
czerasz

1
Зауважте, що це ігнорує нові порожні файли (наприклад, якщо ви торкаєтесь файлу).
РонДжон

Існує багато випадків, коли це дасть той самий md5sum із зовсім іншою структурою файлів та каталогів. Перейменування файлів і каталогів це зовсім не змінить, якщо це не змінить порядок сортування файлів. Тому я б не рекомендував такий підхід.
Ганс-Пітер Штерр

2

Гарна чекова сума дерев - це ідентифікатор дерева Git.

На жаль, не існує автономного інструменту, який міг би це зробити (принаймні, я цього не знаю), але якщо у вас Git під рукою, ви можете просто зробити вигляд, щоб створити нове сховище та додати до індексу файли, які ви хочете перевірити.

Це дозволяє створити (відтворюваний) хеш дерева - який включає лише вміст, імена файлів та деякі скорочені режими файлів (виконувані файли).


2

Як подальший результат до цієї чудової відповіді , якщо ви хочете прискорити обчислення контрольної суми для великого каталогу, спробуйте GNU Parallel :

find -s somedir -type f | parallel -k -n 100 md5 {} | md5

(Для цього використовується Mac з md5, замініть за потребою.)

-kПрапор важливо, що наказує parallelпідтримувати порядок, в іншому випадку загальна сума може змінитися , щоб запустити працювати , навіть якщо ці файли все одно. -n 100каже, щоб запустити кожен екземпляр md5зі 100 аргументів, це параметр, який можна налаштувати для найкращого часу виконання. Дивіться також -Xпрапор parallel(хоча в моєму особистому випадку спричинив помилку.)


1

Сценарій, який добре перевірений і підтримує ряд операцій, включаючи пошук дублікатів, порівняння даних і метаданих, показ доповнень, а також зміни та видалення, вам може сподобатися Fingerprint .

Відбиток пальців зараз не створює єдиної контрольної суми для каталогу, але файл стенограми, який включає контрольні суми для всіх файлів у цьому каталозі.

fingerprint analyze

Це генерується index.fingerprintв поточному каталозі, який включає контрольні суми, назви файлів та розміри файлів. За замовчуванням він використовує і MD5та, і SHA1.256.

В майбутньому я сподіваюся додати підтримку Merkle Trees у Fingerprint, що дасть вам єдину контрольну суму верхнього рівня. Зараз вам потрібно зберегти цей файл для перевірки.


1

Я не хотів нових виконуваних файлів, а також незграбних рішень, тож ось мій:

#!/bin/sh
# md5dir.sh by Camilo Martin, 2014-10-01.
# Give this a parameter and it will calculate an md5 of the directory's contents.
# It only takes into account file contents and paths relative to the directory's root.
# This means that two dirs with different names and locations can hash equally.

if [[ ! -d "$1" ]]; then
    echo "Usage: md5dir.sh <dir_name>"
    exit
fi

d="$(tr '\\' / <<< "$1" | tr -s / | sed 's-/$--')"
c=$((${#d} + 35))
find "$d" -type f -exec md5sum {} \; | cut -c 1-33,$c- | sort | md5sum | cut -c 1-32

0

Міцний і чистий підхід

  • По-перше, спочатку не зависайте доступну пам'ять ! Вилучіть файл шматками, а не подайте весь файл.
  • Різні підходи для різних потреб / цілей (все нижче, або виберіть те, що коли-небудь застосовується):
    • Хешируйте лише ім'я входу всіх записів у дереві каталогів
    • Хеш-вміст файлу всіх записів (залишаючи мета, наприклад, номер inode, ctime, atime, mtime, size і т.д., ви отримуєте ідею)
    • Для символічного посилання його зміст - це назва референта. Хеши його або виріши пропустити
    • Дотримуйтесь або не слідкуйте (вирішена назва) символьного посилання під час хешування вмісту запису
    • Якщо це каталог, його вміст - це лише записи каталогу. Під час рекурсивного переходу вони в кінцевому підсумку будуть хешировані, але чи варто хешировать імена вхідних даних цього рівня для позначення цього каталогу? Корисний у випадках використання, коли хеш потрібен для швидкої ідентифікації зміни без необхідності глибоко переходити до хеш-вмісту. Прикладом можуть бути зміни назви файлу, але решта вмісту залишається однаковою, і всі вони є досить великими файлами
    • Добре обробляти великі файли (знову ж таки, пам’ятайте про оперативну пам’ять)
    • Обробляйте дуже глибокі дерева каталогів (пам’ятайте про дескриптори відкритого файлу)
    • Обробіть нестандартні імена файлів
    • Як діяти з файлами, які є розетками, трубами / FIFO, блоковими пристроями, пристроями для обміну даними? Потрібно також їх хеш?
    • Не оновлюйте час доступу до будь-якого запису під час проїзду, оскільки це буде побічним ефектом та неефективною (інтуїтивно зрозумілою?) Для певних випадків використання.

Це те, що я маю на голові, кожен, хто витратив деякий час на це, практично зловив би інші випадки та кутові справи.

Ось інструмент (відмова від відповідальності: я дописую це) dtreetrawl , дуже легкий у пам’яті, який стосується більшості випадків, може бути трохи нерівним по краях, але був дуже корисним.

Usage:
  dtreetrawl [OPTION...] "/trawl/me" [path2,...]

Help Options:
  -h, --help                Show help options

Application Options:
  -t, --terse               Produce a terse output; parsable.
  -d, --delim=:             Character or string delimiter/separator for terse output(default ':')
  -l, --max-level=N         Do not traverse tree beyond N level(s)
  --hash                    Hash the files to produce checksums(default is MD5).
  -c, --checksum=md5        Valid hashing algorithms: md5, sha1, sha256, sha512.
  -s, --hash-symlink        Include symbolic links' referent name while calculating the root checksum
  -R, --only-root-hash      Output only the root hash. Blank line if --hash is not set
  -N, --no-name-hash        Exclude path name while calculating the root checksum
  -F, --no-content-hash     Do not hash the contents of the file

Приклад, сприятливий для людини:

...
... //clipped
...
/home/lab/linux-4.14-rc8/CREDITS
        Base name                    : CREDITS
        Level                        : 1
        Type                         : regular file
        Referent name                :
        File size                    : 98443 bytes
        I-node number                : 290850
        No. directory entries        : 0
        Permission (octal)           : 0644
        Link count                   : 1
        Ownership                    : UID=0, GID=0
        Preferred I/O block size     : 4096 bytes
        Blocks allocated             : 200
        Last status change           : Tue, 21 Nov 17 21:28:18 +0530
        Last file access             : Thu, 28 Dec 17 00:53:27 +0530
        Last file modification       : Tue, 21 Nov 17 21:28:18 +0530
        Hash                         : 9f0312d130016d103aa5fc9d16a2437e

Stats for /home/lab/linux-4.14-rc8:
        Elapsed time     : 1.305767 s
        Start time       : Sun, 07 Jan 18 03:42:39 +0530
        Root hash        : 434e93111ad6f9335bb4954bc8f4eca4
        Hash type        : md5
        Depth            : 8
        Total,
                size           : 66850916 bytes
                entries        : 12484
                directories    : 763
                regular files  : 11715
                symlinks       : 6
                block devices  : 0
                char devices   : 0
                sockets        : 0
                FIFOs/pipes    : 0

Загальна порада завжди вітається, але найкращі відповіді - конкретні та з кодом, де це доречно. Якщо у вас є досвід використання інструменту, на який ви посилаєтесь, будь ласка, включіть його.
bu5hman

@ bu5hman Звичайно! Мені було не зовсім зручно сказати (похмуро?) Більше про те, як добре це працює, оскільки я беру участь у його розвитку.
шість-к

0

Робиться індивідуально для всіх файлів у кожному каталозі.

# Calculating
find dir1 | xargs md5sum > dir1.md5
find dir2 | xargs md5sum > dir2.md5
# Comparing (and showing the difference)
paste <(sort -k2 dir1.md5) <(sort -k2 dir2.md5) | awk '$1 != $3'

0

Перехід на формат архіву POSIX впливає на контрольні суми на основі GNU Tar

Ця відповідь має бути доповненням до підходу використання виводу Tar для хешування вмісту каталогів, як це було запропоновано (серед іншого) у чудових відповідях Уоррена Янга та Гілла деякий час тому.

З цього моменту принаймні openSUSE (з моменту випуску 12.2) змінив стандартний формат GNU Tar з "GNU tar 1.13.x формат" на (трохи) вищий "POSIX 1003.1-2001 (pax) формат" . Також вгору за течією (серед розробників GNU Tar) вони обговорюють виконання тієї ж міграції, див., Наприклад, останній параграф на цій сторінці посібника з GNU Tar :

Формат за замовчуванням для GNU tar визначається під час компіляції. Ви можете перевірити це, запустивши tar --helpта вивчивши останні рядки його виводу. Зазвичай GNU tar призначений для створення архівів у gnuформаті, однак майбутня версія перейде на posix.

(Ця сторінка також дає хороший огляд різних архівних форматів, доступних у GNU Tar.)

У нашому випадку, коли ми орієнтуємося на вміст каталогів і хешуємо результат, і не вживаючи конкретних заходів, перехід від формату GNU до POSIX має такі наслідки:

  • Незважаючи на однаковий вміст каталогу, отримана контрольна сума буде різною.

  • Незважаючи на однаковий вміст каталогу, отримана контрольна сума буде відрізнятися від запуску до запуску, якщо використовуються заголовки pax за замовчуванням.

Останнє випливає з того, що формат POSIX (pax) включає розширені заголовки pax, які визначаються рядком формату, який за замовчуванням визначається %d/PaxHeaders.%p/%fу GNU Tar. У цьому рядку специфікатор %pзамінюється ідентифікатором процесу генеруючого процесу Tar, який, звичайно, відрізняється від запуску до запуску. Дивіться цей розділ в керівництві GNU Tar і , зокрема , цей для деталей.

Щойно зараз, починаючи з 2019-03-28, існує прийняте зобов’язання, що усуває це питання.

Отже, щоб мати можливість продовжувати використовувати GNU Tar в даному випадку використання, я можу порекомендувати наступні альтернативні варіанти:

  • Використовуйте опцію Tar, --format=gnuщоб явно сказати Tar, щоб створити архів у "старому" форматі. Це обов'язково для підтвердження "старих" контрольних сум.

  • Використовуйте новіший формат POSIX, але явно вкажіть відповідний заголовок pax, наприклад, by --pax-option="exthdr.name=%d/PaxHeaders/%f". Однак це порушує відсталу сумісність із "старими" контрольними сумами.

Ось фрагмент коду Bash, який я регулярно використовую для обчислення контрольних сум вмісту каталогів, включаючи метадані:

( export LC_ALL=C
  find <paths> ! -type s -print0 |
  sort -z |
  tar cp --format=gnu --numeric-owner \
         --atime-preserve \
         --no-recursion --null --files-from - |
  md5sum --binary; )

Тут <paths>замінено пробілом розділений список шляхів усіх каталогів, які я хочу охопити контрольною сумою. Мета використання локальної мови C, розділення нульових байтів імен файлів і використання знаходження та сортування для отримання незалежного порядку файлової системи файлів в архіві вже достатньо обговорюється в інших відповідях.

Навколишні круглі дужки зберігають LC_ALLналаштування місцевого значення в підшарці.

Крім того, я використовую вираз ! -type sз , findщоб уникнути попереджень Tar , які виникають , якщо сокет файли є частиною вмісту каталогу: GNU Tar НЕ архівує сокети. Якщо ви хочете отримувати сповіщення про пропущені розетки, залиште це вираження подалі.

Я використовую --numeric-ownerразом з Tar, щоб пізніше перевірити контрольні суми навіть у системах, де не всі власники файлів відомі.

--atime-preserveВаріант для Tar краще опустити , якщо якийсь - або з <paths>лежиш на змонтоване пристрої тільки для читання. Інакше вас попередить про кожен окремий файл, часова мітка доступу Tar не вдалося відновити. Для ввімкнення запису <paths>я використовую цю опцію, добре, щоб зберегти часові позначки доступу в каталогах хешованих файлів.

Варіант Tar --no-recursion, який уже використовувався в пропозиції Джилла , не дозволяє рекурсивно спускатися в каталоги сам по собі, а працювати замість нього файл по файлу на будь-якому, що його подають з відсортованого findвиводу.

І, нарешті, неправда, якою я користуюсь md5sum: я насправді використовую sha256sum.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.