grep -R
(z wyjątkiem zmodyfikowanego GNU grep
znajdującego się w OS / X 10.8 i nowszych) podąża za dowiązaniami symbolicznymi, więc nawet jeśli jest tam tylko 100 GB plików ~/Documents
, może być /
na przykład dowiązanie symboliczne i skończysz skanować cały system plików łącznie z plikami jak /dev/zero
. Użyj grep -r
z nowszym GNU grep
lub użyj standardowej składni:
find ~/Documents -type f -exec grep Milledgeville /dev/null {} +
(należy jednak pamiętać, że status wyjścia nie odzwierciedla faktu, że wzorzec jest dopasowany, czy nie).
grep
znajduje linie pasujące do wzorca. W tym celu musi ładować jedną linię w pamięci. GNU, grep
w przeciwieństwie do wielu innych grep
implementacji, nie ma ograniczenia rozmiaru linii, które czyta i obsługuje wyszukiwanie w plikach binarnych. Tak więc, jeśli masz plik z bardzo dużą linią (czyli dwiema znakami nowej linii bardzo daleko), większy niż dostępna pamięć, to się nie powiedzie.
Zwykle dzieje się tak z rzadkim plikiem. Możesz go odtworzyć za pomocą:
truncate -s200G some-file
grep foo some-file
Tego trudno obejść. Możesz to zrobić jako (wciąż z GNU grep
):
find ~/Documents -type f -exec sh -c 'for i do
tr -s "\0" "\n" < "$i" | grep --label="$i" -He "$0"
done' Milledgeville {} +
Konwertuje sekwencje znaków NUL na jeden znak nowej linii przed wprowadzeniem danych wejściowych grep
. Obejmuje to przypadki, w których problem wynika z rzadkich plików.
Możesz to zoptymalizować, robiąc to tylko dla dużych plików:
find ~/Documents -type f \( -size -100M -exec \
grep -He Milledgeville {} + -o -exec sh -c 'for i do
tr -s "\0" "\n" < "$i" | grep --label="$i" -He "$0"
done' Milledgeville {} + \)
Jeśli pliki są nie rzadki i masz wersję GNU grep
przed 2.6
, można użyć --mmap
opcji. Linie zostaną zmapowane w pamięci w przeciwieństwie do tam skopiowanych, co oznacza, że system zawsze może odzyskać pamięć, stronicując strony do pliku. Ta opcja została usunięta w GNU grep
2.6
grep
mogą odrzucić bufory, które do tej pory przetworzyły. Możeszgrep
generować dane wyes
nieskończoność bez użycia więcej niż kilku kilobajtów pamięci. Problemem jest rozmiar linii.--null-data
Przydaje się również opcja grep GNU . Wymusza użycie NUL zamiast nowej linii jako terminatora linii wejściowej.Zwyklę robię
Wypróbowałem kilka metod i okazało się, że jest to najszybszy. Zauważ, że nie radzi sobie to dobrze z plikami ze spacjami o nazwie pliku. Jeśli wiesz, że tak jest i masz wersję grep GNU, możesz użyć:
Jeśli nie, możesz użyć:
Który będzie
exec
grep dla każdego pliku.źródło
find -print0 | xargs -0 grep -ne 'expression'
find -print0
ixargs -0
do tej pory: wszystkie trzy BSD, MINIX 3, Solaris 11,…Mogę wymyślić kilka sposobów na obejście tego:
Zamiast grepowania wszystkich plików naraz, zrób jeden plik na raz. Przykład:
Jeśli potrzebujesz tylko wiedzieć, które pliki zawierają słowa, zrób to
grep -l
. Ponieważ grep przestanie szukać po pierwszym trafieniu, nie będzie musiał czytać żadnych dużych plikówJeśli chcesz również rzeczywisty tekst, możesz napisać dwa osobne grep wzdłuż:
źródło
grep
wyjściowe używają separatora zgodnego z nazwami plików). Musisz także zacytować$file
.for
to przetworzenie pliku jako dwóch argumentów)Chwytam dysk o pojemności 6 TB, aby wyszukać utracone dane, i wyczerpałem pamięć - błąd. To powinno działać również dla innych plików.
Rozwiązaniem, które wymyśliliśmy, było odczytanie dysku w porcjach za pomocą dd i grep. To jest kod (big-grep.sh):
źródło