0

Say I'm doing a grep for something and in the results I have a bunch of files? How can I quickly open one of those files in vim without using the mouse and without or typing the name by hand?

For example, with my mouse I can CMD-Click the name of the file and it opens in vim. But I would like to have the same speed without using the mouse.

UPDATE: grep is just one example, I would like to know if there's a universal way to would work for any command. Something like a bash variable that holds the last file name or whatever. And also, it should open just the one file that I want.

Thanks.

1
  • I use tmux to copy/paste the filenames
    – balki
    Commented Jul 10 at 17:31

3 Answers 3

1

When you use grep -l, file names won't be repeated, so you don't need sort | uniq or sort -u.

You can also use -p to open all files in tabs.

grep -rlH "mail" . | xargs vim -p
4
  • That won't open a specific file, it will open all of them. I want to target just one of them... and it would ideally work for any command, not just grep.
    – Cezar
    Commented May 25, 2017 at 13:09
  • @Cezar - the only way to specify which file is to use head -n 1 for the first line or tail -n 1 for the last line. There's no way for bash to know which file you want without more specificity in the commands sent to it.
    – Cometsong
    Commented Jul 14, 2017 at 17:02
  • @Cometsong I'm wondering what is the best way to navigate a project tree from the terminal. Where you have a bunch of files that have the same names and such.
    – Cezar
    Commented Jul 17, 2017 at 12:57
  • 1
    @Cezar - there are options for this: 1) denote the file or the number of the file prior to the cmd running at all; 2) go through every one sequentially, opening each in a vim instance; 3) generate a list at the end of the command (prob easiest using a bash wrapper function) to ask you which one of the resulting files you'd like to open in vim. There is a ton of variability in this type of task - how many files are being queried? how many are in the resulting set? how big is the project?
    – Cometsong
    Commented Jul 17, 2017 at 18:27
1

There's a bunch of ways to target a single file from a list of paths:

Pipe Them into Vim

To target a single file from a list of paths, you can pipe them all into Vim (using your grep example):

grep -rl "needle" . | vim -

You can then navigate to the single file name you're looking for with normal motions and open it with gf.

The slight downside of this approach is that you then have an unsaved buffer with the paths in it. To prevent Vim complaining about this when you try to quit, you can tell Vim this file doesn't need to be saved by setting 'nomodified' or by specifying a nofile 'buftype':

grep -rl "needle" . | vim - +'set nomod'

grep -rl "needle" . | vim - +'set buftype=nofile'

Use the quickfix

Vim allows you to pre-populate the quickfix with a list of files:

vim +copen -q <(grep -rn "needle" .)

You can then jump between the matches with :cn and :cp, or switch to the quickfix window, navigate to the file you want and open it with Enter.

The downside of this is that it will load the first file into a buffer along with any of the others that you visit via the quickfix.

:read ! the List Inside Vim

Another way you can get a shell command's output into Vim is with its :read ! command.

:r !grep -rl "needle" .

Like in the pipe solution, you can then open the file you're interested in with gf.

Select the File Outside Vim

There are any number of ways you could do this, but they're generally outside the scope of this site. One popular way is to install a fuzzy finder, such as fzf.

5
  • 2
    Greetings, fellow -q <(process) appreciator.
    – romainl
    Commented Jul 3 at 12:10
  • While vim - works far better today than it used to, I would probably do vim +'grep -rl needle' .
    – D. Ben Knoble
    Commented Jul 3 at 17:26
  • @D.BenKnoble I've updated my answer to include discussion of :r! in case that's what you meant. I haven't included :grep as a solution because @Cezar indicated in their edit that grep is just an example of a command that generates a list of files.
    – Rich
    Commented Jul 10 at 11:32
  • I think you mean :read !, not :read! (if :read ever gets a meaning for !, it will have the :write problem that :write! and :write ! are different). That wasn't really I referred to, but good improvement nonetheless.
    – D. Ben Knoble
    Commented Jul 10 at 23:48
  • @D.BenKnoble That'd be a backwards incompatible change, so I don't think it's likely to happen, (because they currently behave identically), but I've updated the answer nonetheless. Thanks.
    – Rich
    Commented Jul 11 at 7:40
0

You can make grep print just the file names with grep -l -H. You could then pipe this to sort and uniq to get a list of files. This could then be passed to vim with xargs.

Lets say you wanted to open all files in the current directory or sub directories that contain the word mail, you would type something like this:

grep -r -l -H "mail" . | sort | uniq | xargs vim
2
  • sort -u is the same as sort | uniq with less typing. You should also be able to use grep -rlH mail ;-) Commented May 24, 2017 at 12:40
  • That won't open a specific file, it will open all of them. I want to target just one of them... and it would ideally work for any command, not just grep.
    – Cezar
    Commented May 25, 2017 at 13:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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