Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I once had a version of grep on my PC (I think it came with an early version of Delphi) which supported searching in nested folders with the -r switch. Now something (I suspect a later version of Delphi) has hijacked the old grep and replaced it with something that announces itself thus:

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.

it provides these options for recursion:

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

but I can't make it return results from files within folders, so grep -r fred *.txt will only find files in the current folder containing "fred", and files within subfolders are ignored.

What's the magic option required here?

ANSWER from Rich Homolka is below, but here's my batch wrapper developed from that answer:

:==========================================================================
:   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:"
share|improve this question
    
It's probably not grep, but how you call your command. Are you using Command Prompt, or a UNIX-like shell? (bash, zsh, etc) –  Rich Homolka Jul 15 at 0:12
    
In a shell like sh or bash, that *.txt would be expanded to a list of all the files in the working directory ending in .txt, which would exclude all directories. Have you tried putting the *.txt in single quotes? –  Parthian Shot Jul 15 at 0:17
    
@ParthianShot that would still not do what the poster wanted, which is recursive. –  Rich Homolka Jul 15 at 0:23
    
@ParthianShot grep -r fred "*.txt" gives me *.txt: Invalid argument - which means I'm probably stonkered when it comes to searching files with names with embedded spaces. –  rossmcm Jul 15 at 0:32

2 Answers 2

up vote 3 down vote accepted

Grep is probably working right. Your command is what's off. I answered something similar before here, regarding chown on UNIX, with a UNIX shell. Some of the explanation may be useful.

If you want to check using the recursive flag, you want to pass a directory:

grep -r fred .

This will find fred in any files rooted at ., named *.txt or not.

If you want to limit this to just files named *.txt, you could do this a bit with grep itself:

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

This is obviously a bit clumsy to type every time, but works.

A cleaner way is to use a UNIX style shell (or at least it's too hard to do in command prompt, I don't how to do so).

In unix, for recursive commands, you commonly use the pattern

find file_selection_criteria | xargs command whatever_args

In this case would be:

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

As a simpler thing, if you downloaded a fairly recent shell like bash4 or zsh you could use the new recursive glob (double *):

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

So it really depends on how much work you'd want to do. If you want to just have grep work now, maybe you use the first one, and filter out anything not named .txt. If you do this often, maybe the time invested in getting a UNIX like shell is worth it. You can get one from Cygwin or use a tool or two from MinGW

share|improve this answer
    
Aha! We're close. grep -r fred . finds "fred" in all files in the current folder and subfolders and searches recursively. So how do I do the same thing for only txt files? –  rossmcm Jul 15 at 0:28
    
Thanks @Rich. The "clumsy" option is fine as I wrap the call in a batch file anyway (question updated with the batch file). –  rossmcm Jul 15 at 2:27
    
Of course, one disadvantage of the "clumsy" solution is that all files (matching any extension) in the folder and subfolders are searched, and it is the results that are filtered. –  rossmcm Jul 15 at 2:53

you could use the native find command inside a for loop for the same purpose:

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

here starting from the directory c:\users\administrator\desktop it will recursively (/r) search for the string foo in all (*) files incase-sensitively (/i) alongside displaying their line numbers (/n) if found

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.