13

I often grep a bunch of files to find a line, and then grep returns one result. Rather than copying and pasting the filename into a new command, I'd like to be able to open that one result with an editor. Something like: grep foo | vim. Is there a way to do that in BASH?

18

Use grep -l to just get the filename of the matching file and not the matching text, then combine it with vim:

vim "$(grep -l some_pattern file_names)"
  • Additionally, you can use -q flag of grep to make sure grep has indeed resulted in some matching file: grep -q patterns fnames && vim $(grep -l pattern fnames) – mkc Feb 17 '14 at 18:45
  • Should I make a remark about filenames with spaces? – Bernhard Feb 17 '14 at 19:08
  • @Bernhard It can never hurt, and also about those with newlines and other special characters. I recognise the problem when vi complains, the OP might not. – Anthon Feb 17 '14 at 19:29
4

You can use quickfix or errorfile feature in vim:

$ grep -n foo * > /tmp/foo.list
$ vim -q /tmp/foo.list

Vim will open the first file in /tmp/foo.list and place the cursor directly in the line where foo was found. You can go to the next instance using :cn and previous instance using :cp.

Side note: If you are already using vim or gvim, then I would suggest using its inbuilt grep functionality. Read :help vimgrep for more information.

1

For search in project no need to leave vim with Fugitive

autocmd QuickFixCmdPost *grep* cwindow

Below you can see example of :Ggrep config

enter image description here

0

EDIT: After reading your comment, I realize I didn't understand the question initially. Here is a simple script which takes your search term as an argument and prompts for the path to search. If the result is found in only one file, it opens the file for editing at the location of the search result.

#!/bin/bash

SRCHTRM="$1"

read -p "Where to search: " SRCHPATH

FILEFOUND=$(grep "$SRCHTRM" $SRCHPATH)
FILEFOUNDCNT=$(grep "$SRCHTRM" $SRCHPATH | wc -l)

FILEAWK=$(echo "$FILEFOUND" | awk -F":" '{ print $1 }')

if [ "$FILEFOUNDCNT" -eq "1" ];then
    vi +/"$SRCHTRM" "$FILEAWK"
else
    echo "$1 was found in more than one file"
fi
  • But this seems to allow me to edit the output of grep, but what I want to do is edit the file with the filename that grep returns. – Jonathan Feb 17 '14 at 19:24
0

@devnull got the answer right in this comment:

You were rather close, simply tell vim to read from STDIN:

grep foo | vim -

0

To expand on Anthon's answer for a case where you have more than one match, it may be helpful in some cases to use head -1 (from this answer) to select only the first result: vim "$(grep -l STRING FILES|head -1)"

0

If you are performing a long command that has grep somewhere in the middle of it you can also do

vim `command1 | grep whatever | awk '{do_something_else}'`

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.