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.

  • Check if this is useful : File=grep -r foo /path/of/search/* | grep 'roger' ThirdFile=grep -r foo /path/of/search/* | head -3 | tail -1 – soumyaranjan Jan 18 '16 at 9:29
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++.

  • 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! – dotancohen Jan 18 '16 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. – dotancohen Jan 18 '16 at 12:21
  • Sure, no problem (your link is wrong btw). – Kira Jan 18 '16 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`

  • 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. – dotancohen Jan 18 '16 at 10:11
  • Updated the solution. – soumyaranjan Jan 26 '16 at 6:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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