Jakie polecenie wiersza polecenia systemu Linux może identyfikować takie pliki?
AFAIK find
polecenie (lub grep
) może dopasować tylko określony ciąg znaków w pliku tekstowym. Ale chcę dopasować całą zawartość, tzn. Chcę zobaczyć, które pliki pasują do wyrażenia regularnego \0+
, ignorując znaki końca linii . Może find . cat | grep
idiom może działać, ale nie wiem, jak zrobić grep ignorując linie (i traktować plik jako binarny).
Tło: Co kilka dni, kiedy mój laptop zawiesza się, moja partycja btrfs traci informacje: pliki otwarte do zapisu zostają zastąpione zerami (rozmiar pliku pozostaje mniej więcej nienaruszony). Korzystam z synchronizacji i nie chcę, aby te fałszywe pliki się rozprzestrzeniały: potrzebuję sposobu ich zidentyfikowania, aby móc pobrać je z kopii zapasowej.
źródło
-v
opcję grep: odfiltruj wszystkie pliki, które mają dowolny bajt od 1 do 255.Odpowiedzi:
Możesz
grep
dla ␀ znaków w trybie wyrażenia regularnego Perl:Możesz więc użyć tego:
źródło
GNU grep 2.5.4
. Niezależnie od tego, czy mogę użyć--binary-files=text
lub--binary-files=binary
, dajetrue
wynik dla wszystkich niepustych wartości danych, np."\0\0"
,"\0x\0"
,"abcd"
... Dokładny kod użyłem to:for typ in binary text ;do for dat in '\0\0' '\0x\0' 'abcd' '' ;do printf "$dat" >f; grep --binary-files=$typ -P '[^\0]' f >/dev/null && echo true || echo false; done; done
GNU grep) 2.10
. Ta późniejsza wersja daje oczekiwane wyniki ... więc spóźniona +1printf '\0\n\0\0\n\n' > file
lubprintf '\n' > file
w tym przypadku.\0
ze\n
znaków i (nawet zero każdego z nich) byłby zgodny.Zgadzam się z tym, co mówi D_Bye o znalezieniu źródła problemu.
W każdym razie, aby sprawdzić, czy plik zawiera tylko
\0
i / lub\n
można użyćtr
:Który zwraca 0 dla pustych / nowych linii i pustych plików.
źródło
tr -d '\0\n'
rozwiązuje problem nowej linii, który wtedy pozostawia tylko problem (?) pustych plików wymienionych na wyjściu ... Przetwarza jednak każdy bajt każdego pliku (który może, ale nie musi być problemem) +1Podejrzewam, że te pliki są rzadkie, to znaczy, że nie mają przydzielonego miejsca na dysku, po prostu określają rozmiar pliku (
du
zgłosiłby dla nich 0).W takim przypadku z GNU find możesz to zrobić (zakładając, że żadna ścieżka pliku nie zawiera znaków nowej linii):
źródło
du
zapobiegnie zarysowaniu zawartości każdego pojedynczego pliku w systemie plików, więc cała procedura nie zajmie ponad 30 minut.printf %b
powyżej podaje, codu
by się zgłosiło)-size +0
na-size +1
pliki o zerowej długości, które są wykluczone z wyników. Również pliki zawierające\n
w swojej ścieżce powodują problemy z tym poleceniem.-size +0
jest dla rozmiarów ściśle większych niż 0.-size +1
byłoby dla rozmiarów ściśle większych niż 512. Ograniczenie nowej linii zostało już wspomniane.-size +1
, że naprawdę masz rację. Naprawiłem swoją odpowiedź. :-)Oto mały program w języku Python, który potrafi to zrobić:
I w akcji:
Można sprawdzić wiele plików za pomocą znalezisko'S
-exec
,xargs
GNUparallel
i podobnych programów. Alternatywnie spowoduje to wydrukowanie nazw plików, z którymi należy się uporać:Pamiętaj, że jeśli zamierzasz przekazać dane wyjściowe temu innemu programowi, nazwy plików mogą zawierać znaki nowej linii, więc powinieneś je rozgraniczać inaczej (odpowiednio, za pomocą
\0
).Jeśli masz dużo plików, lepiej byłoby użyć opcji równoległego przetwarzania, ponieważ odczytuje to tylko jeden plik na raz.
źródło
/etc/nologin
,~/.hushlogin
,.nomedia
, ...) są błędnie przez tę odpowiedź.Znajdź pliki zawierające tylko znaki zerowe „0” i znaki nowego wiersza „n”.
Funkcja
q
in sed powoduje, że każde wyszukiwanie pliku kończy się natychmiast po znalezieniu w wierszu dowolnego znaku o wartości innej niż zero.Utwórz pliki testowe
wynik
źródło
-print0
argument wydaje się być brakujefind
lubIFS=
część jest pomieszane. Jaki był zamierzony ogranicznik?To jedna wkładka jest najbardziej skutecznym sposobem na znalezienie 100% przy użyciu plików nul GNU
find
,xargs
orazgrep
(zakładając, że jest ona zbudowana z obsługą PCRE):Zalety tej metody w porównaniu z innymi podanymi odpowiedziami to:
Permission denied
ostrzeżeń.grep
przestanie czytać dane z plików po znalezieniu dowolnego bajtu innego niż nul (LC_ALL=C
służy do upewnienia się, że każdy bajt jest interpretowany jako znak ).grep
procesów skutecznie sprawdza wiele plików.-
są obsługiwane poprawnie.Przekazywanie
-Z
opcjigrep
i używaniexargs -r0 ...
pozwala na wykonanie dalszych działań na plikach 100% NUL (np .: czyszczenie):Polecam również korzystanie z
find
opcji,-P
aby uniknąć następujących dowiązań symbolicznych i-xdev
aby uniknąć przechodzenia przez systemy plików (np. Zdalne montowanie, drzewa urządzeń, montowanie powiązań itp.).Aby zignorować znaki końca linii , powinien działać następujący wariant (choć nie sądzę, że to dobry pomysł):
Złożenie wszystkiego razem, w tym usunięcie niechcianych plików (100% znaków nul / nowej linii), aby zapobiec ich tworzeniu kopii zapasowej:
Nie polecam dołączania pustych plików (zero bajtów), często istnieją one w bardzo specyficznych celach .
źródło
\0
z 900 MB dziury) i aktualny czas wyników. Jeśli zrobisz to w sposób, który będzie dla ciebie przekonujący, najprawdopodobniej będzie przekonujący dla nas wszystkich-P
jest domyślnie wfind
. Jeśli chcesz podążać za dowiązaniami symbolicznymi, to-L
/-follow
. Przekonasz się, że POSIX nawet nie określa tej opcjifind
(chociaż POSIX jest tym, który wprowadził te -P / -H / -L dla kilku poleceń).Do korzystania z GNU sed możesz użyć
-z
opcji, która definiuje linię jako łańcuchy zakończone zerem i dopasowują i usuwają puste linie w następujący sposób:Polecenie główne pomiędzy nimi jest tylko optymalizacją.
źródło
Pyton
Pojedynczy plik
Zdefiniuj alias:
Sprawdź to:
Wiele plików
Znajdź wszystkie pliki binarne rekurencyjnie:
Aby znaleźć wszystkie pliki niebinarne, zmień za
&&
pomocą||
.źródło