Jak uzyskać sumę MD5 zawartości katalogu jako jedną sumę?


171

Program md5sum nie zapewnia sum kontrolnych dla katalogów. Chcę uzyskać jedną sumę kontrolną MD5 dla całej zawartości katalogu, w tym plików w podkatalogach. To jest jedna połączona suma kontrolna wykonana ze wszystkich plików. Czy jest na to sposób?

Odpowiedzi:


186

Właściwy sposób zależy od tego, dlaczego pytasz:

Opcja 1: Porównaj tylko dane

Jeśli potrzebujesz skrótu zawartości pliku drzewa, to załatwi sprawę:

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

Najpierw podsumowuje całą zawartość pliku osobno, w przewidywalnej kolejności, a następnie przekazuje tę listę nazw plików i skrótów MD5 do samodzielnego mieszania, co daje pojedynczą wartość, która zmienia się tylko, gdy zmienia się zawartość jednego z plików w drzewie.

Niestety find -sdziała tylko z BSD find (1), używanym w macOS, FreeBSD, NetBSD i OpenBSD. Aby uzyskać coś porównywalnego w systemie z GNU lub SUS find (1), potrzebujesz czegoś nieco brzydszego:

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

Zastąpiliśmy find -stelefonem na numer sort. -k 2Nieco informuje go przeskoczyć mieszania MD5, a więc tylko sortuje nazwy plików, które są w polu 2 przez end-of-line, przez sort„s liczenia.

Ta wersja polecenia ma słabość, ponieważ może się zdezorientować, jeśli masz jakieś nazwy plików z nowymi liniami, ponieważ będzie to wyglądało jak wiele linii do sortwywołania. find -sWariant nie ma tego problemu, ponieważ przechodzenie drzewa i sortowania zdarzyć w tym samym programie find.

W obu przypadkach sortowanie jest konieczne, aby uniknąć fałszywych trafień: najpopularniejsze systemy plików Unix / Linux nie utrzymują list katalogów w stabilnej, przewidywalnej kolejności. Możesz nie zdawać sobie z tego sprawy z używania lsi takich, które dyskretnie sortują zawartość katalogu za Ciebie. findbez -slub sortwywołanie będzie drukować pliki w dowolnej kolejności, w jakiej system plików je zwraca, co spowoduje, że to polecenie da zmienioną wartość skrótu, jeśli kolejność plików przekazanych mu jako dane wejściowe ulegnie zmianie.

Może być konieczna zmiana md5sumpoleceń na md5lub inna funkcja skrótu. Jeśli wybierzesz inną funkcję skrótu i ​​potrzebujesz drugiej formy polecenia dla swojego systemu, może być konieczne odpowiednie dostosowanie sortpolecenia. Inną pułapką jest to, że niektóre programy sumujące dane w ogóle nie wypisują nazw plików, czego najlepszym przykładem jest stary sumprogram uniksowy .

Ta metoda jest nieco nieefektywna, md5sumponieważ wywołuje N + 1 razy, gdzie N jest liczbą plików w drzewie, ale jest to konieczny koszt, aby uniknąć mieszania metadanych plików i katalogów.

Opcja 2: Porównaj dane i metadane

Jeśli musisz być w stanie wykryć, że coś w drzewie się zmieniło, a nie tylko zawartość pliku, poproś taro spakowanie zawartości katalogu, a następnie wyślij ją na adres md5sum:

$ tar -cf - somedir | md5sum

Ponieważ tarwidzi także uprawnienia do plików, prawa własności itp., Wykrywa to również zmiany tych rzeczy, a nie tylko zmiany zawartości plików.

Ta metoda jest znacznie szybsza, ponieważ powoduje tylko jedno przejście przez drzewo i uruchamia program mieszający tylko raz.

Podobnie jak w przypadku findpowyższej metody, tarnazwy plików będą przetwarzane w kolejności, w jakiej system plików je zwraca. Może się zdarzyć, że we wniosku możesz mieć pewność, że tak się nie stanie. Mogę wymyślić co najmniej trzy różne wzorce użytkowania tam, gdzie jest to prawdopodobne. (Nie zamierzam ich wymieniać, ponieważ wchodzimy na terytorium nieokreślonego zachowania. Każdy system plików może być tutaj inny, nawet od jednej wersji systemu operacyjnego do następnej).

Jeśli okaże się, że otrzymujesz fałszywe wyniki, polecam skorzystanie z find | cpioopcji w odpowiedzi Gillesa .


7
Myślę, że najlepiej jest przejść do porównywanego katalogu i użyć find .zamiast niego find somedir. W ten sposób nazwy plików są takie same przy podawaniu różnych specyfikacji ścieżek do znalezienia; może to być trudne :-)
Abbafei,

Czy powinniśmy też sortować pliki?
CMCDragonkai

@CMCDragonkai: Co masz na myśli? W pierwszym przypadku mamy nie posortować listę nazw plików. W drugim przypadku celowo tego nie robimy, ponieważ część podkreślonego czegokolwiek w pierwszym zdaniu polega na tym, że kolejność plików w katalogu zmieniła się, więc nie chcesz nic sortować.
Warren Young,

@WarrenYoung Czy możesz wyjaśnić nieco dokładniej, dlaczego opcja 2 nie zawsze jest lepsza? Wydaje się być szybszy, prostszy i bardziej wieloplatformowy. W którym przypadku nie powinna to być opcja 1?
Robin Winslow,

Opcja 1 alternatywa: find somedir -type f -exec sh -c "openssl dgst -sha1 -binary {} | xxd -p" \; | sort | openssl dgst -sha1zignorowanie wszystkich nazw plików (powinno działać z nowymi wierszami)
windm

38

Suma kontrolna musi stanowić deterministyczną i jednoznaczną reprezentację plików w postaci łańcucha. Deterministyczny oznacza, że ​​jeśli umieścisz te same pliki w tych samych lokalizacjach, otrzymasz ten sam wynik. Jednoznaczność oznacza, że ​​dwa różne zestawy plików mają różne reprezentacje.

Dane i metadane

Tworzenie archiwum zawierającego pliki to dobry początek. Jest to jednoznaczna reprezentacja (oczywiście, ponieważ można odzyskać pliki przez rozpakowanie archiwum). Może zawierać metadane pliku, takie jak daty i własność. Jednak nie jest to jeszcze w porządku: archiwum jest niejednoznaczne, ponieważ jego reprezentacja zależy od kolejności przechowywania plików i, jeśli dotyczy, od kompresji.

Rozwiązaniem jest sortowanie nazw plików przed ich zarchiwizowaniem. Jeśli twoje nazwy plików nie zawierają nowych linii, możesz uruchomić, find | sortaby je wyświetlić, i dodać je do archiwum w tej kolejności. Zachowaj ostrożność, aby powiedzieć archiwizatorowi, aby nie wracał do katalogów. Oto przykłady z POSIX pax, GNU tar i 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

Tylko nazwy i treść, w sposób mało zaawansowany technologicznie

Jeśli chcesz wziąć pod uwagę tylko dane pliku, a nie metadane, możesz utworzyć archiwum zawierające tylko zawartość pliku, ale nie ma do tego standardowych narzędzi. Zamiast dołączać zawartość pliku, możesz dołączyć skrót plików. Jeśli nazwy plików nie zawierają znaków nowej linii, a są tylko zwykłe pliki i katalogi (bez dowiązań symbolicznych lub plików specjalnych), jest to dość łatwe, ale musisz zadbać o kilka rzeczy:

{ 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

Oprócz wykazu sum kontrolnych dołączamy listę katalogów, ponieważ w przeciwnym razie puste katalogi byłyby niewidoczne. Lista plików jest posortowana (w określonym, powtarzalnym języku - dzięki Peter.O za przypomnienie mi o tym). echooddziela dwie części (bez tego można utworzyć puste katalogi, których nazwa wygląda jak md5sumdane wyjściowe, które można również przekazać zwykłym plikom). Dołączamy również listę rozmiarów plików, aby uniknąć ataków polegających na przedłużaniu długości .

Nawiasem mówiąc, MD5 jest przestarzałe. Jeśli jest dostępny, rozważ użycie SHA-2 lub przynajmniej SHA-1.

Nazwy i dane, obsługujące znaki nowej linii w nazwach

Oto wariant powyższego kodu, który wykorzystuje narzędzia GNU do oddzielania nazw plików bajtami zerowymi. Dzięki temu nazwy plików mogą zawierać znaki nowej linii. Narzędzia GNU digest cytują w swoich wynikach znaki specjalne, więc nie będzie dwuznacznych znaków nowej linii.

{ 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

Bardziej niezawodne podejście

Oto minimalnie przetestowany skrypt Pythona, który tworzy skrót opisujący hierarchię plików. Bierze katalogi i zawartość pliku na konta i ignoruje dowiązania symboliczne i inne pliki oraz zwraca błąd krytyczny, jeśli nie można odczytać żadnego pliku.

#! /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()

OK, to działa, dzięki. Ale czy można to zrobić bez uwzględnienia jakichkolwiek metadanych? Teraz potrzebuję go tylko do samej zawartości.

Co powiesz LC_ALL=C sortna sprawdzanie z różnych środowisk ... (+ 1 btw)
Peter.O

Stworzyłeś do tego cały program Python? Dzięki! To naprawdę więcej niż się spodziewałem. :-) W każdym razie sprawdzę te metody, a także nową opcję 1 autorstwa Warrena.

Dobra odpowiedź. Ustawienie kolejności sortowania za pomocą LC_ALL=Cjest niezbędne, jeśli działa na wielu komputerach i systemach operacyjnych.
Davor Cubranic,

Co cpio -o -znaczy Czy cpio domyślnie nie używa standardowego wejścia / wyjścia? Produkuje GNU cpio 2.12cpio: Too many arguments
Jan Tojnar,

12

Spójrz na md5deep . Niektóre funkcje md5deep, które mogą Cię zainteresować:

Operacja rekurencyjna - md5deep może rekurencyjnie sprawdzać całe drzewo katalogów. To znaczy, oblicz MD5 dla każdego pliku w katalogu i dla każdego pliku w każdym podkatalogu.

Tryb porównania - md5deep może zaakceptować listę znanych skrótów i porównać je z zestawem plików wejściowych. Program może wyświetlać te pliki wejściowe, które pasują do listy znanych skrótów lub te, które nie pasują.

...


Fajnie, ale nie mogę go uruchomić, mówi .../foo: Is a directory, co daje?
Camilo Martin

3
Sam md5deep nie rozwiązuje problemu OP, ponieważ nie drukuje skonsolidowanego md5sum, po prostu drukuje md5sum dla każdego pliku w katalogu. To powiedziawszy, możesz md5 zsumować wyjście md5deep - nie do końca to, czego chciał OP, ale jest blisko! np. dla bieżącego katalogu: md5deep -r -l -j0 . | md5sum(gdzie -rjest rekurencyjny, -loznacza „użyj ścieżek względnych”, aby bezwzględna ścieżka do plików nie kolidowała podczas próby porównania zawartości dwóch katalogów, i -j0oznacza użycie 1 wątku, aby zapobiec niedeterminizmowi z powodu do poszczególnych sum md5 zwracanych w różnych zamówieniach).
Stevie

Jak zignorować niektóre pliki / katalogi na ścieżce?
Sandeepan Nath,

9

Jeśli Twoim celem jest znalezienie różnic między dwoma katalogami, rozważ użycie diff.

Spróbuj tego:

diff -qr dir1 dir2

Tak, to też jest przydatne. Myślę, że miałeś na myśli dir1 dir2 w tym poleceniu.

1
Zwykle nie używam GUI, kiedy mogę ich uniknąć, ale do różnicowania katalogów kdiff3 jest świetny i działa również na wielu platformach.
sinelaw

Za pomocą tego polecenia zgłaszane są również różne pliki.
Serge Stroobandt

7

Możesz haszować każdy plik rekurencyjnie, a następnie haszować wynikowy tekst:

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

Wymagany jest md5deep .


1
zamiast md5deepużywać hashdeepna Ubuntu 16.04, ponieważ pakiet md5deep jest tylko przejściowym manekinem dla hashdeep.
palik

1
Próbowałem hashdeep. Wyprowadza nie tylko skróty, ale także nagłówek, w tym, ## Invoked from: /home/myuser/dev/która jest twoją bieżącą ścieżką i ## $ hashdeep -s -r -l ~/folder/. Zostało to posortowane, więc końcowy skrót będzie inny, jeśli zmienisz swój bieżący folder lub wiersz poleceń.
truf

3

Tylko zawartość pliku , z wyjątkiem nazw plików

Potrzebowałem wersji, która sprawdzała tylko nazwy plików, ponieważ zawartość znajduje się w różnych katalogach.

Ta wersja (odpowiedź Warrena Younga) bardzo pomogła, ale moja wersja md5sumwypisuje nazwę pliku (w stosunku do ścieżki, z której uruchomiłem polecenie), a nazwy folderów były różne, dlatego mimo że sumy kontrolne poszczególnych plików były dopasowane, końcowa suma kontrolna nie „t.

Aby to naprawić, w moim przypadku po prostu musiałem usunąć nazwę pliku z każdego wiersza findwyniku (wybierz tylko pierwsze słowo oddzielone spacjami cut):

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

Konieczne może być również posortowanie sum kontrolnych, aby uzyskać odtwarzalną listę.
eckes

3

rozwiązanie :

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

działa szybkie i łatwiejsze rozwiązanie niż skrypt bash.

patrz dokument: https://pypi.python.org/pypi/checksumdir/1.0.5


jeśli nie masz pip, być może będziesz musiał go zainstalować z yum -y zainstaluj python-pip (lub dnf / apt-get)
DmitrySemenov

3

nix-hashz menedżera pakietów Nix

Polecenie nix-hash oblicza skrót kryptograficzny zawartości każdej ścieżki i drukuje go na standardowym wyjściu. Domyślnie oblicza skrót MD5, ale dostępne są również inne algorytmy skrótu. Hash jest drukowany w systemie szesnastkowym.

Hash jest obliczany na podstawie serializacji każdej ścieżki: zrzutu drzewa systemu plików zrootowanego na ścieżce. Umożliwia to mieszanie katalogów i dowiązań symbolicznych, a także zwykłych plików. Zrzut jest w formacie NAR utworzonym przez nix-store --dump. Zatem ścieżka hash nix daje taki sam hash kryptograficzny jak ścieżka nix-store --dump path | md5sum.


2

Używam tego mojego fragmentu kodu do umiarkowanych ilości :

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

i ten dla XXXL :

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


Co robi -xdevflaga?
czerasz

Wzywa Cię do man find
wpisania

Słuszna uwaga :-). -xdev Don't descend directories on other filesystems.
czerasz

1
Pamiętaj, że ignoruje to nowe, puste pliki (na przykład po dotknięciu pliku).
RonJohn

Istnieje wiele przypadków, w których da to tę samą sumę md5 z zupełnie inną strukturą plików i katalogów. Zmiana nazw plików i katalogów w ogóle tego nie zmieni, jeśli nie zmieni kolejności sortowania plików. Więc nie poleciłbym tego podejścia.
Hans-Peter Störr

2

Dobra suma kontrolna drzewa to identyfikator drzewa Git.

Niestety nie ma dostępnego samodzielnego narzędzia, które by to zrobiło (przynajmniej nie wiem), ale jeśli masz pod ręką Gita, możesz po prostu udawać, że tworzysz nowe repozytorium i dodajesz pliki, które chcesz sprawdzić do indeksu.

Pozwala to na wytworzenie (odtwarzalnego) skrótu drzewa - który zawiera tylko zawartość, nazwy plików i niektóre zredukowane tryby plików (wykonywalne).


2

W następstwie tej doskonałej odpowiedzi , jeśli chcesz przyspieszyć obliczanie sumy kontrolnej dla dużego katalogu, wypróbuj GNU Parallel :

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

(To używa komputera Mac z md5, w razie potrzeby zamień).

-kFlaga jest ważne, który nakazuje parallel, aby utrzymać porządek, inaczej całkowita suma może zmienić uruchomić uruchomić nawet jeśli pliki są takie same. -n 100mówi, aby uruchomić każdą instancję md5z 100 argumentami, jest to parametr, który można dostosować, aby uzyskać najlepszy czas działania. Zobacz także -Xflagę parallel(choć w moim osobistym przypadku spowodował błąd).


1

Skrypt, który jest dobrze przetestowane i wspiera szereg działań, w tym znalezienie duplikatów, robienie porównań zarówno na danych i metadanych, pokazując uzupełnień, a także zmiany i usuwania, może chcesz papilarnych .

Odcisk palca w tej chwili nie tworzy pojedynczej sumy kontrolnej dla katalogu, ale plik transkrypcji, który zawiera sumy kontrolne dla wszystkich plików w tym katalogu.

fingerprint analyze

To wygeneruje index.fingerprintw bieżącym katalogu, który zawiera sumy kontrolne, nazwy plików i rozmiary plików. Domyślnie używa zarówno MD5i SHA1.256.

W przyszłości mam nadzieję dodać obsługę linii papilarnych do odcisku palca, która da ci jedną sumę kontrolną najwyższego poziomu. W tej chwili musisz zachować ten plik do weryfikacji.


1

Nie chciałem nowych plików wykonywalnych ani niezgrabnych rozwiązań, więc oto moje zdanie:

#!/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

Solidne i czyste podejście

  • Po pierwsze, nie usuwaj dostępnej pamięci ! Hashuj plik w porcjach zamiast karmić cały plik.
  • Różne podejścia do różnych potrzeb / celów (wszystkie poniżej lub wybierz to, co kiedykolwiek dotyczy):
    • Hash tylko nazwa pozycji wszystkich pozycji w drzewie katalogów
    • Hash zawartość pliku wszystkich wpisów (pozostawiając meta jak, numer i-węzła, ctime, atime, mtime, rozmiar itp., Masz pomysł)
    • W przypadku dowiązania symbolicznego jego zawartością jest nazwa referencyjna. Hash to lub wybierz pominąć
    • Śledź lub nie, aby śledzić (nazwa rozwiązana) dowiązanie symboliczne podczas mieszania zawartości wpisu
    • Jeśli jest to katalog, jego zawartość to tylko wpisy katalogu. Podczas przechodzenia rekurencyjnie zostaną one w końcu zaszyfrowane, ale czy nazwy pozycji katalogu na tym poziomie powinny być zaszyfrowane, aby oznaczyć ten katalog? Przydatne w przypadkach użycia, w których skrót jest wymagany do szybkiego zidentyfikowania zmiany bez konieczności głębokiego przechodzenia do mieszania zawartości. Przykładem mogą być zmiany nazw plików, ale reszta zawartości pozostaje taka sama i wszystkie są dość dużymi plikami
    • Dobrze obsługuj duże pliki (ponownie, pamiętaj o pamięci RAM)
    • Obsługa bardzo głębokich drzew katalogów (uwaga na otwarte deskryptory plików)
    • Obsługa niestandardowych nazw plików
    • Jak postępować z plikami, które są gniazdami, potokami / FIFO, urządzeniami blokowymi, urządzeniami char? Czy też je musisz mieszać?
    • Nie aktualizuj czasu dostępu do żadnego wpisu podczas podróży, ponieważ będzie to efekt uboczny i przyniesie efekt przeciwny do zamierzonego (intuicyjny?) W niektórych przypadkach użycia.

To właśnie mam na głowie, każdy, kto spędził trochę czasu nad tym, praktycznie nad tym przyłapałby inne problemy i sprawy narożne.

Oto narzędzie (zrzeczenie się: jestem współtwórcą) dtreetrawl , bardzo lekki w pamięci, który dotyczy większości przypadków, może być nieco szorstki na brzegach, ale był dość pomocny.

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

Przykładowy wynik przyjazny dla człowieka:

...
... //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

Ogólne porady są zawsze mile widziane, ale najlepsze odpowiedzi są konkretne i zawierają kod, jeśli to konieczne. Jeśli masz doświadczenie w korzystaniu z narzędzia, do którego się odwołujesz, dołącz je.
bu5hman

@ bu5hman Pewnie! Nie czułem się swobodnie mówiąc (radośnie?) Więcej o tym, jak dobrze działa, ponieważ jestem zaangażowany w jego rozwój.
six-k

0

Robi się indywidualnie dla wszystkich plików w każdym katalogu.

# 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

Migracja do formatu archiwum POSIX wpływa na sumy kontrolne oparte na GNU Tar

Ta odpowiedź ma być dodatkową aktualizacją podejścia polegającego na wykorzystaniu danych wyjściowych Tar do mieszania zawartości katalogów, jak zaproponowano (między innymi) w doskonałych odpowiedziach Warrena Younga i Gillesa jakiś czas temu.

Od tego czasu przynajmniej openSUSE (od czasu wydania 12.2) zmienił domyślny format GNU Tar z formatu GNU tar 1.13.x” na (nieco) lepszy „format POSIX 1003.1-2001 (pax)” . Również upstream (wśród twórców GNU tar) dyskutują aby wykonać tę samą migracji, patrz na przykład ostatni akapit na tej stronie w podręczniku GNU tar :

Domyślny format tar GNU jest określany podczas kompilacji. Możesz to sprawdzić, uruchamiając tar --helpi sprawdzając ostatnie wiersze jego wyniku. Zwykle GNU tar jest skonfigurowany do tworzenia archiwów w gnuformacie, jednak przyszła wersja przełączy się na posix.

(Ta strona zawiera również niezłą recenzję różnych formatów archiwów dostępnych w GNU Tar.)

W naszym przypadku, w którym tarujemy zawartość katalogu i mieszamy wynik, i bez podjęcia szczególnych działań, zmiana z GNU na POSIX ma następujące konsekwencje:

  • Mimo identycznej zawartości katalogu wynikowa suma kontrolna będzie inna.

  • Pomimo identycznej zawartości katalogu wynikowa suma kontrolna będzie różna od uruchomienia do uruchomienia, jeśli zostaną użyte domyślne nagłówki pax.

To ostatnie wynika z faktu, że format POSIX (pax) zawiera rozszerzone nagłówki pax, które są określone przez ciąg formatu domyślnie ustawiony %d/PaxHeaders.%p/%fw GNU Tar. W tym ciągu specyfikator %pjest zastępowany identyfikatorem procesu generującego proces Tar, który oczywiście różni się w zależności od uruchomienia. Zobacz tę sekcję instrukcji GNU Tar, aw szczególności tę, aby poznać szczegóły.

Właśnie teraz, datowany na 28.03.2019, zatwierdzono wcześniej zatwierdzenie, które rozwiązuje ten problem.

Tak więc, aby móc nadal używać GNU Tar w danym przypadku użycia, mogę polecić następujące alternatywne opcje:

  • Użyj opcji Tar, --format=gnuaby wyraźnie powiedzieć Tarowi, aby wygenerował archiwum w „starym” formacie. Jest to obowiązkowe, aby sprawdzić „stare” sumy kontrolne.

  • Użyj nowszego formatu POSIX, ale jawnie określ odpowiedni nagłówek pax, na przykład przez --pax-option="exthdr.name=%d/PaxHeaders/%f". Jednak łamie to zgodność wsteczną ze „starymi” sumami kontrolnymi.

Oto fragment kodu Bash, którego regularnie używam do obliczania sum kontrolnych zawartości katalogu, w tym metadanych:

( 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; )

Tutaj <paths>zastępuje się rozdzieloną spacjami listą ścieżek wszystkich katalogów, które chcę objąć sumą kontrolną. Cel użycia ustawień narodowych C, separacja plików o pustych bajtach oraz użycie funkcji Znajdź i Sortuj w celu uzyskania niezależnej od systemu plików kolejności plików w archiwum jest już wystarczająco omówione w innych odpowiedziach.

Otaczające nawiasy utrzymują LC_ALLustawienie lokalne w podpowłoce.

Ponadto, używam wyrażenia ! -type sze finduniknąć ostrzeżeń ze smoły, które występują, gdy pliki gniazdowe są częścią zawartości katalogu: GNU tar nie archiwalnych gniazd. Jeśli wolisz otrzymywać powiadomienia o pomijanych gniazdach, zostaw to wyrażenie.

Korzystam --numeric-ownerz Tar, aby móc później zweryfikować sumy kontrolne nawet w systemach, w których nie wszyscy właściciele plików są znani.

--atime-preserveRozwiązaniem dla Tar jest lepiej pominąć, jeżeli którykolwiek z <paths>spoczywa na tylko do odczytu zamontowanego urządzenia. W przeciwnym razie zostaniesz ostrzeżony dla każdego pliku, którego sygnatury czasowej dostępu Tar nie udało się przywrócić. Aby włączyć zapis <paths>, używam tej opcji, aby zachować znaczniki czasu dostępu w hashowanych katalogach.

Opcja Tar --no-recursion, która była już używana w propozycji Gillesa , zapobiega samemu rekurencyjnemu zejściu Tar do katalogów i zamiast tego działa plik po pliku na czymkolwiek, co otrzymuje z posortowanego findwyjścia.

I wreszcie nie jest prawdą, że używam md5sum: faktycznie używam sha256sum.


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.