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

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.