Windows XP - Jak używać grep do znajdowania ciągów w plikach w podkatalogach

1

Kiedyś miałem wersję grep na moim komputerze (myślę, że pochodziła z wczesną wersją Delphi), która wspierała wyszukiwanie w zagnieżdżonych folderach za pomocą -r przełącznik. Teraz coś (podejrzewam, że późniejsza wersja Delphi) przejęło starą grep i zastąpiło ją czymś, co ogłasza się tak:

C:\PROJECTS\>grep --version
grep (GNU grep) 2.4.2

Copyright 1988, 1992-1999, 2000 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

udostępnia te opcje rekursji:

-d, --directories=ACTION  how to handle directories
                          ACTION is 'read', 'recurse', or 'skip'.
-r, --recursive           equivalent to --directories=recurse.

ale nie mogę przywrócić wyników z plików w folderach, więc grep -r fred *.txt znajdzie tylko pliki w bieżącym folderze zawierające „fred”, a pliki w podfolderach są ignorowane.

Jaka jest tu wymagana magiczna opcja?

ODPOWIEDŹ z Rich Homolka jest poniżej, ale oto moje opakowanie partii opracowane na podstawie tej odpowiedzi:

:==========================================================================
:   GrepExt - searches files matching an extension recursively for a string 
:
:   Usage   : call GrepExt <regex string to search for>  <extension>
:   Example : call GrepExt "procedure\ *Add" pas
:
:   Notes   : - quotes only needed if regex contains spaces
:             - remove the first "-i" for case-sensitive search 
:             - the second "-i" ensures the case of the extension doesn't matter     
:             - ErrorLevel set to 0 if there were any matches, 1 otherwise
:             - this is very inefficient when the folders contain a large
:               number of files that don't match the extension, as *all* files
:               are grepped and the results are then grepped to filter out
:               the hits from files that don't match the extension.         
:
@echo off
grep -i -r "%~1" . | grep -i "^[^:]*\.%~2:"
rossmcm
źródło
Prawdopodobnie nie jest to grep, ale jak nazywasz swoje polecenie. Czy używasz wiersza polecenia lub powłoki podobnej do UNIX? (bash, zsh itp.)
Rich Homolka
W skorupie sh lub bash, to *.txt zostanie rozwinięty do listy wszystkich plików w katalogu roboczym zakończonym na .txt, co wykluczałoby wszystkie katalogi. Próbowałeś umieścić *.txt w pojedynczych cudzysłowach?
Parthian Shot
@ParthianShot, który nadal nie zrobiłby tego, co chciał plakat, co jest rekurencyjne.
Rich Homolka
@ParthianShot grep -r fred "*.txt" daje mi *.txt: Invalid argument - co oznacza, że ​​prawdopodobnie mam kłopoty z wyszukiwaniem plików o nazwach z osadzonymi spacjami.
rossmcm

Odpowiedzi:

3

Grep prawdopodobnie działa dobrze. Twoje polecenie jest wyłączone. Odpowiedziałem wcześniej na coś podobnego tutaj , dotyczące chown w UNIX, z powłoką UNIX. Niektóre wyjaśnienia mogą być przydatne.

Jeśli chcesz sprawdzić za pomocą flagi rekurencyjnej, chcesz przekazać katalog:

grep -r fred .

To znajdzie fred w dowolnych plikach zakorzenionych w., O nazwie * .txt lub nie.

Jeśli chcesz ograniczyć to tylko do plików o nazwie * .txt, możesz to zrobić trochę z samym grep:

grep -r fred . | grep '^[^:]*\.txt:'

To jest oczywiście trochę niezgrabne, by pisać za każdym razem, ale działa.

Czystszym sposobem jest użycie powłoki w stylu UNIX (lub przynajmniej jest to zbyt trudne do wykonania w wierszu poleceń, nie wiem jak to zrobić).

W unixie dla poleceń rekurencyjnych często używa się wzorca

find file_selection_criteria | xargs command whatever_args

W tym przypadku byłoby:

find . -name '*.txt' | xargs grep fred

W uproszczeniu, jeśli pobrałeś całkiem nową powłokę, taką jak bash4 lub zsh, możesz użyć nowego rekurencyjnego globu (double *):

shopt -s globstar # needed for bash4
grep fred ./**/*.txt

Więc tak naprawdę zależy od tego, ile pracy chcesz wykonać. Jeśli chcesz teraz pracować w grep, możesz użyć pierwszego i odfiltrować wszystko, co nie ma nazwy .txt. Jeśli robisz to często, może warto zainwestować czas w uzyskanie powłoki podobnej do UNIX. Możesz go zdobyć Cygwin lub użyj narzędzia lub dwóch z nich MinGW

Rich Homolka
źródło
Aha! Byli blisko. grep -r fred . znajduje „fred” w wszystko pliki w bieżącym folderze i podfolderach i przeszukuje rekurencyjnie. Więc jak mam zrobić to samo tylko za txt pliki?
rossmcm
Dzięki @Rich. Opcja „niezdarny” jest w porządku, ponieważ i tak zawijam połączenie w pliku wsadowym (pytanie zaktualizowane plikiem wsadowym).
rossmcm
Oczywiście jedną z wad „niezdarnego” rozwiązania jest to wszystko przeszukiwane są pliki (pasujące do dowolnego rozszerzenia) w folderze i podfolderach, a wyniki są filtrowane.
rossmcm
0

możesz użyć native find polecenie wewnątrz a for pętla do tego samego celu:

for /r c:\users\administrator\desktop %a in (*) do @find /i /n "foo" %a

tutaj zaczynając od katalogu c:\users\administrator\desktop będzie rekurencyjnie ( /r ) wyszukaj ciąg foo we wszystkim ( * ) pliki są wrażliwe ( /i ) wraz z wyświetlaniem ich numerów linii ( /n ) Jeśli znaleziono

w17t
źródło