Lepiej wyjaśnić na przykładach.
Mogę:
find . -name "*.py" -type f > output.txt
Ale jak mogę zapisać wynik w tym samym pliku dla:
find . -name "*.py" -type f -exec grep "something" {} \
Nie mogę po prostu zrobić
find . -name "*.py" -type f -exec grep "something" {} \ > output.txt
Odpowiedź
Jeśli dobrze Cię rozumiem, oto co chcesz zrobić:
find . -name "*.py" -print0 | xargs -0 grep "something" > output.txt
Znajdź wszystkie pliki z rozszerzeniem .py
, grep
tylko wiersze zawierające something
i zapisz wiersze w output.txt
. Jeśli plik output.txt
istnieje, zostanie obcięty, w przeciwnym razie zostanie utworzony.
Używając -exec
:
find . -name "*.py" -exec grep "something" {} \; > output.txt
Łączę Chrisa Downsa komentarz tutaj: Powyższe polecenie spowoduje wykonanie grep
tyle razy, ile find
znajdzie ścieżki, które przejdą dane testy (tylko jeden powyżej). Jeśli jednak zmienisz \;
na +
, grep
zostanie wywołany z wieloma nazwami ścieżek from find
(do pewnego limitu).
Zobacz pytanie Używając średnika (;) kontra plus ( +) z exec w find , aby uzyskać więcej informacji na ten temat.
Komentarze
Odpowiedź
Jeśli chcesz zapisać wszystkie pasujące wiersze we wszystkich plikach w output.txt
, ostatnie polecenie działa, z wyjątkiem tego, że brakuje wymaganego ;
na końcu polecenia.
find . -name "*.py" -type f -exec grep "something" {} \; > output.txt
Jeśli chcesz, aby każde uruchomienie grep
generowało wyjście do innego pliku, uruchom powłokę, aby obliczyć nazwę pliku wyjściowego i wykonać przekierowanie.
find . -name "*.py" -type f -exec sh -c "grep "something" <"$0" >"$0.txt"" {} \;
Komentarze
- ostatni naprawdę fajny: D
- Aby rozwinąć @gilles, odpowiedz, aby była trochę bardziej pouczająca, zwłaszcza jeśli lista plików, które ' jest duży, możesz zgłosić nazwę pliku (ścieżkę względną) każdego pliku wraz z wynikami grep ' ed, używając tego:
find . -name "*.py" -type f -exec grep "something" {} \; -print > output.txt
A jeśli ' chciałbyś zobaczyć e numery wierszy grep ' ed, możesz oczywiście użyćgrep -n "something"
Odpowiedź
Dla przypomnienia, grep
ma --include
oraz --exclude
argumenty, których można użyć do filtrowania przeszukiwanych plików:
grep -r --include="*.py" "something" > output.txt
Komentarze
- Co najmniej GNU
grep
tak.
Odpowiedź
Użyj tee
:
find . -name "*.py" | tee output.txt | xargs grep "something"
Zastrzeżenie: jeśli masz jakieś pliki ze znakami specjalnymi (w tym spacjami), które xargs
i grep
nie działają dobrze z (a file.txt
zostanie zinterpretowany jako dwa pliki, a
i file.txt
). Alternatywą jest użycie -x
lub -print0
, ale którekolwiek z nich spowoduje zanieczyszczenie output.txt
. -x
użyje \
do zmiany znaczenia niektórych znaków specjalnych i będzie to output.txt
.-print0
użyje bajtu zerowego jako separatora pól (co również wymaga xargs -0
) i output.txt
będzie wyglądać jak jedna długa, ciągła linia tekstu.
To, jak sobie z tym poradzisz, zależy od Ciebie.
Odpowiedź
grep -n CThread "`find . -name "*.cpp"`"
+
zamiast\;
, znacznie skróci czas wykonywania (ponieważ będzie zawierał argumenty przed wykonaniem doARG_MAX
).grep -H
, jeśli chcesz dołączyć nazwę pliku do wyniku.LC_ALL=C
tuż przedxargs
, aby uzyskać dużo dodatkowej prędkości. Możesz też użyć flagi-P6
naxargs
, aby działać równolegle z (w tym przypadku) 6 procesami (możesz zmienić liczbę od 6 do wyższego lub niższego, aby zobaczyć, co ' działa szybciej na twoim komputerze i podczas wyszukiwania). Źródła: unix.stackexchange.com/questions/131535/…+
zamiast\;
przekaże wiele plików do programu grep, a jeśli którykolwiek plik w tym zestawie zawiera tekst ' coś ', wszystkie te pliki przejdą test. Więc nie ' nie zrobisz tego, co chcesz.