I can use % to get the name of the focused window for commands. How can I get a space-separated list of all buffers for use in a command?

For example, I would like to call

:!cat [all]

where [all] is something that evaluates to what I want.

  • 1
    Hi. Welcome to Vi/Vim SE. Either :args or :buffers/:ls depending on what value you have for :set hidden? :) Less cryptically, do you navigate files mostly with :next/:prev or other means?
    – B Layer
    Commented Aug 27, 2019 at 10:36
  • 1
    I use :e having :set hidden. I hope my edit clarifies what I mean, thank you. Commented Aug 27, 2019 at 11:29
  • 2
    for the argument list, have a look at :h :_## Commented Aug 27, 2019 at 11:58
  • where [all] is something that evaluates Note that the whole line after ! is simply passed to the shell. You have either to use execute, or pass the value inside an environment variable (so shell can expand it).
    – Matt
    Commented Aug 27, 2019 at 12:03
  • 1
    @AugustJanse It's a "special" (:h cmdline-special). Yes, the specials get expanded as a step separate from normal evaluation. So they are pretty much restricted. Therefore, you'll have to use :execute very often (that's a sort of "eval operator" for Vim). Another possible alternative is the expression register (<C-R>=), but an interactive input is not always convenient.
    – Matt
    Commented Aug 28, 2019 at 8:14

1 Answer 1


I suppose by "open files" you mean active buffers (see :h windows-intro). That could be achieved with the command :ls a (use h-flag to get hidden buffers if needed).

To pack it into a function you could use a redirection or a dedicated getbufinfo() interface. For example

function! GetActiveBuffers()
    let l:blist = getbufinfo({'bufloaded': 1, 'buflisted': 1})
    let l:result = []
    for l:item in l:blist
        "skip unnamed buffers; also skip hidden buffers?
        if empty(l:item.name) || l:item.hidden
        call add(l:result, shellescape(l:item.name))
    return l:result

" the result is a list
" use join() when a single string is needed
":exec '!cat' join(GetActiveBuffers())
  • 2
    instead of parsing the output of :ls, you can use the getbufinfo() function Commented Aug 27, 2019 at 12:42
  • @ChristianBrabandt Thank you. I knew there must be something like this...
    – Matt
    Commented Aug 27, 2019 at 13:12
  • 1
    With :!cat $myargs you're likely to run into escaping issues (it's actually probably going to ruin your use of shellescape()!) Much better is :execute '!cat' join(GetActiveBuffers()), which would assemble the command-line in Vim, rather than use a variable expansion in the spawned shell. (Hint: test it with files containing spaces and special characters and you'll see the difference.)
    – filbranden
    Commented Aug 27, 2019 at 15:00
  • 1
    @filbranden Yes, you're right. It turns out that it's quite hard to escape the things in the right way. exec looks easier to deal with.
    – Matt
    Commented Aug 27, 2019 at 15:46

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.