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 -s
dział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 -s
telefonem na numer sort
. -k 2
Nieco 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 sort
wywołania. find -s
Wariant 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 ls
i takich, które dyskretnie sortują zawartość katalogu za Ciebie. find
bez -s
lub sort
wywoł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 md5sum
poleceń na md5
lub 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 sort
polecenia. 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 sum
program uniksowy .
Ta metoda jest nieco nieefektywna, md5sum
ponieważ 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ś tar
o spakowanie zawartości katalogu, a następnie wyślij ją na adres md5sum
:
$ tar -cf - somedir | md5sum
Ponieważ tar
widzi 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 find
powyższej metody, tar
nazwy 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 | cpio
opcji w odpowiedzi Gillesa .
find .
zamiast niegofind 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 :-)find somedir -type f -exec sh -c "openssl dgst -sha1 -binary {} | xxd -p" \; | sort | openssl dgst -sha1
zignorowanie wszystkich nazw plików (powinno działać z nowymi wierszami)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 | sort
aby 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 POSIXpax
, GNU tar i cpio: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:
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).
echo
oddziela dwie części (bez tego można utworzyć puste katalogi, których nazwa wygląda jakmd5sum
dane 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.
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.
źródło
LC_ALL=C sort
na sprawdzanie z różnych środowisk ... (+ 1 btw)LC_ALL=C
jest niezbędne, jeśli działa na wielu komputerach i systemach operacyjnych.cpio -o -
znaczy Czy cpio domyślnie nie używa standardowego wejścia / wyjścia? Produkuje GNU cpio 2.12cpio: Too many arguments
Spójrz na md5deep . Niektóre funkcje md5deep, które mogą Cię zainteresować:
źródło
.../foo: Is a directory
, co daje?md5deep -r -l -j0 . | md5sum
(gdzie-r
jest rekurencyjny,-l
oznacza „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-j0
oznacza użycie 1 wątku, aby zapobiec niedeterminizmowi z powodu do poszczególnych sum md5 zwracanych w różnych zamówieniach).Jeśli Twoim celem jest znalezienie różnic między dwoma katalogami, rozważ użycie diff.
Spróbuj tego:
źródło
Możesz haszować każdy plik rekurencyjnie, a następnie haszować wynikowy tekst:
Wymagany jest md5deep .
źródło
md5deep
używaćhashdeep
na Ubuntu 16.04, ponieważ pakiet md5deep jest tylko przejściowym manekinem dla hashdeep.## 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ń.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
md5sum
wypisuje 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
find
wyniku (wybierz tylko pierwsze słowo oddzielone spacjamicut
):źródło
rozwiązanie :
działa szybkie i łatwiejsze rozwiązanie niż skrypt bash.
patrz dokument: https://pypi.python.org/pypi/checksumdir/1.0.5
źródło
nix-hash
z menedżera pakietów Nixźródło
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 -
źródło
-xdev
flaga?man find
-xdev Don't descend directories on other filesystems.
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).
źródło
W następstwie tej doskonałej odpowiedzi , jeśli chcesz przyspieszyć obliczanie sumy kontrolnej dla dużego katalogu, wypróbuj GNU Parallel :
(To używa komputera Mac z
md5
, w razie potrzeby zamień).-k
Flaga jest ważne, który nakazujeparallel
, aby utrzymać porządek, inaczej całkowita suma może zmienić uruchomić uruchomić nawet jeśli pliki są takie same.-n 100
mówi, aby uruchomić każdą instancjęmd5
z 100 argumentami, jest to parametr, który można dostosować, aby uzyskać najlepszy czas działania. Zobacz także-X
flagęparallel
(choć w moim osobistym przypadku spowodował błąd).źródło
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.
To wygeneruje
index.fingerprint
w bieżącym katalogu, który zawiera sumy kontrolne, nazwy plików i rozmiary plików. Domyślnie używa zarównoMD5
iSHA1.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.
źródło
Nie chciałem nowych plików wykonywalnych ani niezgrabnych rozwiązań, więc oto moje zdanie:
źródło
Solidne i czyste podejście
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.
Przykładowy wynik przyjazny dla człowieka:
źródło
Robi się indywidualnie dla wszystkich plików w każdym katalogu.
źródło
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 :
(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/%f
w GNU Tar. W tym ciągu specyfikator%p
jest 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=gnu
aby 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:
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_ALL
ustawienie lokalne w podpowłoce.Ponadto, używam wyrażenia
! -type s
zefind
uniknąć 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-owner
z 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-preserve
Rozwią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 posortowanegofind
wyjścia.I wreszcie nie jest prawdą, że używam
md5sum
: faktycznie używamsha256sum
.źródło
Jeśli nie potrzebujesz md5, możesz spróbować
źródło