I have started learning Vim word-search using * and # while the cursor is over the current word. But this search is limited to the current file buffer.

Is there a command or a shortcut to extend this search to:

  1. all opened tabs?
  2. all opened buffers?

It's actually the default behaviour although it may be hard to notice: try * then change to another tab and use n ans N in command mode to jump forward and backward between search hits.

This may make more sense if first you turn highlighting on for all hits:

:set hlsearch
  • 1
    +1 only because of hlsearch that I didn't know, and which I would have search for one day or another :-). However, by default I have tried * #, n and N, and it doesn't jump to other file buffers... Jan 3 '13 at 15:10
  • 1
    No, n and N do not jump buffers (they wrap around), but the term they target is searched for in all tabs; hit * with the highlighting on then cycle thru your tabs -- they will all be highlighted with the same term, so you can use n and N locally there without a fresh search.
    – goldilocks
    Jan 3 '13 at 15:28
  • 2
    The whole point is NOT to have to cycle through your tabs to find all the matches.
    – Magnus
    Jun 26 '14 at 18:16
  • 1
    @Magnus While that may be preferable, it's actually not explicitly stated in the question, which asks how to "extend this search to...all buffers" -> it is extended across all buffers. The point of my answer was to make this clear, since it might not be, especially if you do not have hlsearch set.
    – goldilocks
    Jun 26 '14 at 18:33
 :bufdo vimgrepadd yoursearchterm % | copen

I don't have an exact solution for your problem, hopefully a better answer than mine will come up. But this is how I tackled the problem of finding a word in all buffers.

" enables to search in all open buffers with :Search <pattern>
command! -nargs=1 Search call setqflist([]) | silent bufdo grepadd! <args> %

nnoremap <left>  :cprev<cr>zvzz
nnoremap <right> :cnext<cr>zvzz

The first line creates a command Search with the search pattern as argument, which writes the results in a quickfix list. The two other lines map the (at least for me) useless arrow keys to something useful; they are mapped to jump to the next/previous Search or to the next/previous compile error, etc., they simply step throu the quickfix list. You can use this as follows:

:Search foobar
  • I love this command, but added a few things so it will escape search terms better, and force a redraw. (using silent with splits can cause vim ui to bug out). command! -nargs=1 Search call setqflist([]) | silent execute "bufdo grepadd! '<args>' %" | redraw!
    – Igorio
    Jul 21 '14 at 4:30
  • you can also just type :cn or :cp to switch to the next document.
    – phyatt
    Apr 10 '17 at 20:36

As I've found myself frequently doing this I mashed up an (improvable) script.

You or someone else might find it useful.

Short explanation:

Basically it searches buffer list and show result in quickfix-window.

Two basic commands is added.

  1. Search <pattern> : Search all buffers for <pattern>.
  2. Search1 <pattern> : Search all buffers for <pattern>, but only show first result for each buffer. Typically useful for listing all buffers where function, variable foo is used, (or what ever).

Use bang (:Search! foo) to append to results.

Additionally GSearch and GSearch1 is added where difference is that with Search the script add regex delimiter, e.g.:

foo -> /foo/

Where as GSearch expect it to be enclosed.

The j flag is always added to prevent jump.


There are some hacks to prevent error listing while at the same time keeping the code short. try / catch was a bit cumbersome on bufdo.

let s:not_idents = split("/!#$%&\"`´¨'¯()*+,-.:;<=>?¿@[\]^{|}µ¶·¸~±×÷®©«»¬­ª°º¹²³¼½¾", '\zs')
" Create a delimited pattern. "
fun! s:Parse_pat(pat)
    for c in s:not_idents
        if stridx(a:pat, c) == -1
            return c . a:pat . c
    echohl Error
    echom "Could not delimit pattern '". a:pat ."'"
    echohl None
    return ''

fun! s:AllBufSearch(pat, bang, uno, isg)
    if a:isg
        let pat = a:pat
        let pat = s:Parse_pat(a:pat)
    if pat == ''
    let [_buf, _view] = [bufnr("%"), winsaveview()]
    let _foldenable = &foldenable
    set nofoldenable

    " Copy of current qflist. "
    let qfc = getqflist()
    " Hack to prevent error if no matches. "
    call setqflist([{}])
    silent execute "bufdo vimgrepadd! " . pat . "j %"
    " Restore "
    exec "buffer " . _buf
    let &foldenable = _foldenable
    call winrestview(_view)
    " Fix "
    let qf = getqflist()
    call remove(qf, 0)
    " Only one listing per buffer. "
    if a:uno
        let bn = {}
        let i  = 0
        for m in qf
            if has_key(bn, m["bufnr"])
                call remove(qf, i)
                let bn[m["bufnr"]] = 1
                call remove(qf[i], "valid")
                let i += 1
    if a:bang == "!"
        let qf = qfc + qf
    " If any matches, copen. "
    if len(qf)
        call setqflist(qf)

command! -nargs=1 -bang Search   call s:AllBufSearch(<q-args>, "<bang>", 0, 0)
command! -nargs=1 -bang Search1  call s:AllBufSearch(<q-args>, "<bang>", 1, 0)
command! -nargs=1 -bang GSearch  call s:AllBufSearch(<q-args>, "<bang>", 0, 1)
command! -nargs=1 -bang GSearch1 call s:AllBufSearch(<q-args>, "<bang>", 1, 1)

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.