2

How might I more easily use a filename found by grep as an argument to vim:

$ grep -r foo * lib/beatles/john.c lib/pantera/phil.c lib/pinkfloyd/roger.c lib/pinkfloyd/richard.c lib/whitestripes/elephant/jack.c $ vim lib/pinkfloyd/roger.c 

To autocomplete with Bash, I need to type " l \t p \t i \t r \t o \t" because many other files match. Is there an easer way to say "Give me the third found file?" Maybe something like one of these:

$ vim $3 // Third line $ vim 'roger' // Only line with string 'roger' $ vim TabTabTab // Each Tab completes a different filename from grep 

I do use Tmux and I know that I can go up and select the filename and then paste it. But that is still a bit clumsy, even as a VIM user. There must be a better way!

Note that I am not looking for a solution to script the grep output, rather this is something that I will be using manually as I grep for and open files with VIM.

EDIT: I am looking for a general solution, not one that will always target 'roger' or always target the third item.

1
  • Check if this is useful : File=grep -r foo /path/of/search/* | grep 'roger' ThirdFile=grep -r foo /path/of/search/* | head -3 | tail -1CommentedJan 18, 2016 at 9:29

2 Answers 2

2

I've made a script to grep recursively for a pattern, and then I can select one of the matches so vim will open that file in that line. I call it vgrep (vim grep, although it uses also awk in it). The following is its code:

#!/bin/bash my_grep() { grep -Rn -I --color=auto --exclude-dir={.svn,.git} --exclude={tags,cscope.out} "$@" . 2>/dev/null } my_grep_color() { grep -Rn -I --color=always --exclude-dir={.svn,.git} --exclude={tags,cscope.out} "$@" . 2>/dev/null } awk '{ print NR, $0 }' <(my_grep_color "$@") awk '{ lines[NR]=$1; } END{ printf "Enter index: " getline num < "-"; split(lines[num], s, ":") system("vim "s[1]" +"s[2]) }' <(my_grep "$@") 

I'm calling grep twice just to highlight my matches, you can change it so it will be called only once, but you will lose the highlighting.

Usage:

Suppose you want open vim in the line where there is a word "Foo" in it, you can use it like this: vgrep Foo

If there is a file foobar like:

a b c Bar e f Foo g h i 

vgrep will output this:

1 ./foobar:3 e f Foo g Enter index: 

So you can type 1+enter and it will open that file in the third line. It will output one indexed line for each match it finds.

I'm pretty sure this script can be improved, but for my uses it works just fine.


Also, consider using ctags and cscope if you are working with C/C++.

3
  • Thank you! This doesn't really fit the use case that I had in mind, but it is a better solution for 99% of the time. Nice work!CommentedJan 18, 2016 at 12:18
  • Kira, I put my useful scripts in my [dotfiles git repo](). Would you mind if I put this script there as well? Of course, it is attributed to you and to this post.CommentedJan 18, 2016 at 12:21
  • Sure, no problem (your link is wrong btw).
    – Kira
    CommentedJan 18, 2016 at 12:29
0

Check if this is useful :

File=`grep -r foo /path/of/search/* | grep 'roger'`

WhichItem=3

ThirdFile=`grep -r foo /path/of/search/* | head -$WhichItem | tail -1`

2
  • That would be useful if I always wanted 'roger' or always wanted the third item. I am looking for a general solution. I will add that to the question. Thank you.CommentedJan 18, 2016 at 10:11
  • Updated the solution.CommentedJan 26, 2016 at 6:59

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.