Tip #354: Find in files - recursively (NOT :grep!). Only for unix clones.
tip karma |
Rating 19/12, Viewed by 3150
|
Read and edit this tip on the
Vim tip wiki.
The wiki may have a more recent version of this tip.
created: |
|
October 30, 2002 4:31 |
|
complexity: |
|
basic |
author: |
|
Karthick Gururaj |
|
as of Vim: |
|
5.7 |
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 . '| xargs file '
" Filter out the text files
let com_string = com_string . "| awk '/text/ {print $1}' "
" Some formatting to remove the trailing ':'
let com_string = com_string . "| sed 's/://' "
" grep for the pattern in all the files
let com_string = com_string . '| xargs grep -n ' . a:1
Cheers!
Karthick.
<< Swap caps-lock and control keys using MS Windows Registry |
Comment Lines according to a given filetype >>
Additional Notes
[email protected],
October 30, 2002 4:55
|
I don't know about grep on HP-UX, but GNU grep *can* recurse into directories using either the "-d recurse", or "--recursive" options.
|
[email protected],
October 30, 2002 21:05
|
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?
|
Anonymous,
November 16, 2002 18:02
|
You can even abbreviate that as -r for GNU grep. I often do something like
grep -r 'some_func(' .
Really convenient.
|
shawn at deleurme dot calm.,
June 13, 2003 12:57
|
or, if you can't get GNU grep (which you should) you can always use:
find . | xargs grep whatever
|
[email protected],
June 18, 2003 13:21
|
Or, from within vim:
:grep whatever `find . -name "*.cpp"`
or whatever
|
Anonymous,
August 25, 2003 13:38
|
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
|
|