Vim Tips Wiki
Advertisement

Previous TipNext Tip

Tip: #354 - Find in files recursively

Created: October 30, 2002 4:31 Complexity: basic Author: Karthick Gururaj Version: 5.7 Karma: 19/12 Imported from: Tip#354

You probably know about the grep command in vim (:help grep)

There is one limitation of this - you can't search for a pattern recursively in files (why doesn't grep have some kind of -R option for searching recursively? Have looked around enough at the man pages for that..). The script below does this. Cut-paste this in to your .vimrc/_vimrc. Type ":Fif" (without arguments) to see usage.


" Start of script 
" Location where the temporary file (.fif.tmp) would be stored 
let g:Fif_tmp_dir = "/tmp" 
function! Fif_fun(...) 
if a:0 == 0 
" Print usage info and quit 
echo "Usage: Fif <pattern-to-be-searched> <file-pattern>. E.g:" 
echo "Fif struct *.c" 
echo "searches for the word struct in all the c files from the current directory" 
return 
endif 
if a:0 != 2 
echohl Error 
echo "Error! Wrong number of arguments. Type :Fif with no arguments to see usage" 
echohl None 
return 
endif 
let tmp_file = g:Fif_tmp_dir . "/.fif.tmp" 
execute "!touch " . tmp_file . " 2> /dev/null" 
if ! filewritable(tmp_file) 
echohl Error 
echo "No permissions to create " . tmp_file 
echo "Try setting the g:Fif_tmp_dir variable to the right value" 
echohl None 
return 
endif 
" Put quotes around the file pattern 
let com_string = '!find . -name "' . a:2 . '" ' 
" Do NOT put quotes around the pattern to be searched - leave it to the user 
let com_string = com_string . '-exec grep -n ' . a:1 . ' /dev/null {} \; > ' . tmp_file 
execute com_string 
if ! filereadable(tmp_file) 
echohl Error 
echo "Can't open " . tmp_file . " for reading" 
echohl None 
return 
endif 
execute "cfile " . tmp_file 
execute '!rm -f ' . tmp_file . ' 2> /dev/null' 
endfunction 
com -nargs=* Fif call Fif_fun(<f-args>) 
" End of script. 


No vim magic here, just some shell util usage.

Tested on HPUX.

Should work on Windows with Cygwin. You'll have to

1. Remove those /dev/null's

2. Make sure that the Cygwin's find and grep utils are used, and not the windows ones

3. Change the default value of g:Fif_tmp_dir

4. Cygwin's grep differs from the version I have on HP. For forcing grep to print the filename, you'll have to give it a "-H" option, in addition to "-n"


Some more tinkering can be done with this.. for instance, if you want to search in all the text files, irrespective of the extention, you can consider doing something like this:


" Find all files. 
let com_string = '!find . -type f -print ' 
" Get the file type 
let com_string = com_string . '

Comments

I don't know about grep on HP-UX, but GNU grep *can* recurse into directories using either the "-d recurse", or "--recursive" options.

ctechols--AT--mindspring.com , October 30, 2002 4:55


Mea culpa. Maxima culpa. The version of grep I have in HP does *not* have the "-d recurse" feature, but yes, the GNU grep has, and I have the GNU grep now. Thanks for the information.

- Karthick. PS: Is there a way to remove a tip from these archives?

stonnedsnake--AT--yahoo.com , October 30, 2002 21:05


You can even abbreviate that as -r for GNU grep. I often do something like

grep -r 'some_func(' . 

Really convenient.

Anonymous , November 16, 2002 18:02


or, if you can't get GNU grep (which you should) you can always use:


find . | xargs grep whatever



shawn at deleurme dot calm. , June 13, 2003 12:57


Or, from within vim:

grep whatever `find . -name "*.cpp"`

or whatever

scottu--AT--apptechsys.com , June 18, 2003 13:21


Give this a try.

grep -i "looking for someting" *.c */*.c *.h */*.h */*/*.h

I think this could work for you, unless I am missunderstanding the problem.

~rs3

Anonymous , August 25, 2003 13:38


Advertisement