I know that the register % contains the full path of the current buffer. But how to get the full path of another buffer by its number?

Is there such a function/command in VIM?

I want to explain how I came to this question...

There were 2 buffers open. The first was an XML file in the left window and the other was an XSD file in the right window. I edited both of them. During the editing I wanted to validate the XML against the schema.

However the command

!xmllint --schema /tmp/schema.xsd %

of course worked well only if the current buffer was the one with the XML. So I was curious about whether it would be possible to replace /tmp/schema.xsd with some command or function call that would determine the full path by the buffer number. Something like:

!xmllint --schema getBufferPath(3) %
  • Does :ls help much? Oct 31, 2016 at 17:34
  • @EricRenouf It only shows me the list of buffers
    – ka3ak
    Oct 31, 2016 at 17:54
  • For me it shows the buffer number and the path to the file in it (if applicable), though it's not always the full path Oct 31, 2016 at 18:13

1 Answer 1


You can use the expand() call. For example

:echo expand("#2:p")

Will print the full path of the file in buffer #2 you can list all buffers with :ls

You can use other modifiers and other keywords (For full info page look at :help expand())

Here is an quick excerpt:

           When {expr} starts with '%', '#' or '<', the expansion is done
            like for the cmdline-special variables with their associated
            modifiers.  Here is a short overview:

                   %               current file name
                    #               alternate file name
                    #n              alternate file name n
                    <cfile>         file name under the cursor
                    <afile>         autocmd file name
                    <abuf>          autocmd buffer number (as a String!)
                    <amatch>        autocmd matched name
                    <sfile>         sourced script file name
                    <slnum>         sourced script file line number
                    <cword>         word under the cursor
                    <cWORD>         WORD under the cursor
                    <client>        the {clientid} of the last received
                                    message server2client()
                    :p              expand to full path
                    :h              head (last path component removed)
                    :t              tail (last path component only)
                    :r              root (one extension removed)
                    :e              extension only

                    :let &tags = expand("%:p:h") . "/tags"
            Note that when expanding a string that starts with '%', '#' or
            '<', any following text is ignored.  This does NOT work:
                    :let doesntwork = expand("%:h.bak")
            Use this:
  • Thanks. I executed: :!xmllint --schema #12:p #11:p and it worked. It is much shorter than to type each time the full paths.
    – ka3ak
    Oct 31, 2016 at 18:35

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .