Mam skrypt powłoki, w którym muszę sprawdzić, czy dwa pliki zawierają te same dane, czy nie. Robię to dla wielu plików, aw moim skrypcie diff
polecenie wydaje się być wąskim gardłem wydajności.
Oto linia:
diff -q $dst $new > /dev/null
if ($status) then ...
Czy może istnieć szybszy sposób porównywania plików, może niestandardowy algorytm zamiast domyślnego diff
?
diff
icmp
.Odpowiedzi:
Wierzę,
cmp
że zatrzyma się przy pierwszej bajcie różnicy:źródło
cmp -s $old $new
działa również.-s
jest skrótem od--silent
cmp
sprawdzi najpierw rozmiar pliku. Oto wersja GNU, jeśli chcesz zobaczyć dodatkowe optymalizacje, które zawiera: git.savannah.gnu.org/cgit/diffutils.git/tree/src/cmp.cLubię @Alex Howansky użył do tego „cmp --silent”. Ale potrzebuję zarówno pozytywnej, jak i negatywnej odpowiedzi, więc używam:
Następnie mogę uruchomić to w terminalu lub za pomocą ssh, aby sprawdzić pliki względem stałego pliku.
źródło
echo success
polecenie (lub cokolwiek innego, które umieścisz na jego miejscu) nie powiedzie się, zostanie wykonane polecenie „odpowiedź negatywna”. Powinieneś użyć konstrukcji „jeśli-to-inaczej-fi”. Na przykład jak ten prosty przykład .Dlaczego nie masz skrótu zawartości obu plików?
Wypróbuj ten skrypt, wywołaj go na przykład script.sh, a następnie uruchom w następujący sposób: script.sh plik1.txt plik2.txt
źródło
1/(2^511)
. O ile nie martwisz się, że ktoś celowo spróbuje stworzyć kolizję, pomysł tej metody wywołującej fałszywy alarm nie jest poważnym problemem.cmp
jest jednak jeszcze bardziej wydajny, ponieważ nie musi czytać całego pliku w przypadku, gdy pliki się nie zgadzają.Ponieważ ssę i nie mam wystarczającej liczby punktów reputacji, nie mogę dodać tego smakołyka jako komentarza.
Ale jeśli zamierzasz użyć
cmp
polecenia (i nie potrzebujesz / nie chcesz być gadatliwy), możesz po prostu pobrać status wyjścia. Nacmp
stronę podręcznika :Więc możesz zrobić coś takiego:
źródło
cmp --silent $FILE1 $FILE2 ; if [ "$?" == "1" ]; then echo "files differ"; fi
który z kolei jest bardziej skomplikowany,cmp --silent $FILE1 $FILE2 || echo "files differ"
ponieważ można bezpośrednio użyć polecenia w wyrażeniu. Zastępuje$?
. W rezultacie status polecenia zostanie porównany. I to właśnie robi druga odpowiedź. btw. Jeśli ktoś ma--silent
problem, nie jest obsługiwany wszędzie (busybox). use-s
W przypadku plików, które nie są różne, każda metoda będzie wymagać całkowitego odczytania obu plików, nawet jeśli odczyt był w przeszłości.
Nie ma alternatywy. Tak więc tworzenie skrótów lub sum kontrolnych w pewnym momencie wymaga odczytania całego pliku. Duże pliki wymagają czasu.
Pobieranie metadanych pliku jest znacznie szybsze niż czytanie dużego pliku.
Czy istnieją jakieś metadane plików, których można użyć do ustalenia, że pliki są różne? Rozmiar pliku ? a nawet wyniki polecenia file, które odczytuje tylko niewielką część pliku?
Fragment kodu przykładowego rozmiaru pliku:
Jeśli pliki są tego samego rozmiaru, oznacza to, że nie możesz odczytać pełnych plików.
źródło
ls -n
aby uniknąć problemów, jeśli nazwy użytkowników lub grup mają spacje.Spróbuj także użyć polecenia cksum:
Polecenie cksum wyświetli liczbę bajtów pliku. Zobacz „man cksum”.
źródło
md5
czyta cały plik, więccmp
zatrzymanie się przy pierwszej różnicy będzie znacznie szybsze.Przeprowadzając testy z Raspberry Pi 3B + (używam nakładkowego systemu plików i muszę okresowo synchronizować), uruchomiłem własne porównanie dla diff -q i cmp -s; zwróć uwagę, że jest to dziennik z wnętrza / dev / shm, więc prędkości dostępu do dysku nie stanowią problemu:
Uruchomiłem to kilka razy. cmp -s konsekwentnie miał nieco krótsze czasy na polu testowym, którego używałem. Więc jeśli chcesz używać cmp -s do robienia rzeczy między dwoma plikami ...
źródło