For each filename, Vim generates (relatively) unique filename for it's swap cache directory.

Let's say I would like to store some information for each file (like swap files do), e.g. with :

silent execute '! echo PreciousMetaDataAboutFile ' | tee -a '.$HOME.'/.cache/TreasureChest/fileswap.txt'


  • how to generate fileswap filename , that corresponds to each file path, so files ~/x.rs and /tmp/x.rs will have different metadata files in TreasureChest directory?

I would like to put is as part of function in vim.rc file, so feel free to use multi line syntax.

P.S. from https://vi.stackexchange.com/a/27889/7263 I learned about %, fnameescape(expand('%')) , but I am too newbe in vimscripting to be sure how to properly use it in this context.

  • 1
    Thank you for your feedback @BLayer ! Could you give me feedback if now it's better? Nov 22, 2021 at 13:20

1 Answer 1


The swapfile full path is available through swapname() which takes a buffer name. The current buffer name is available with bufname() with no arguments. So this prints the swapfile path of the current buffer

echo swapname(bufname())

If you want just the filename you'd use fnamemodify() along with the filename modifier :t (for "tail"). And if you want to remove the .swp file extension add :r (for "root") to that. Putting it all together this will print just the root of the swapfile:

echo fnamemodify(swapname(bufname()), ":t:r")

So, following your example, you could then create a string containing a path, the swapname and a new extension like so:

let metafile = $HOME . '/.cache/TreasureChest/ . fnamemodify(swapname(bufname()), ":t:r") . '.txt'

(I'm just storing it in a variable to illustrate things here. You can manipulate it however you need to.)

Note that I'm assuming a configuration with 'directory' set and ending with double slash (see :h 'directory') because doing this encodes the edited file's path in the filename itself and thus the swapfile name alone will be unique. If you instead are configured to store swap files in the same directory as the edited file then you may get filename collisions. In that case you may want to use the full swapfile path as a sub-directory of your metadata file storage directory which means you wouldn't want to strip the path:

let metafile = $HOME . '/.cache/TreasureChest . fnamemodify(swapname(bufname()), ":r") . '.txt'

Of course, if you're using this scheme you don't even need swapname() you can just manipulate the the edited file path directly with, for instance, expand('%:p')!

An alternative to using sub-directories would be to do a similar encoding to that of Vim, i.e. when 'directory' is set and ends with // Vim takes the full path of the edited file and substitutes percent sign for each forward slash. (The swapfile with this name is then stored in a temporary directory.)

So, using the aforementioned expand(), that would look something like...

let metafile = $HOME . '/.cache/TreasureChest/ .
    \ substitute(expand('%:p'), '/', '%', 'g') . '.txt'
  • From fast experiments in Vim session looks promising. I need a moment (later or another day) to try to integrate into script to see how it plays out there! :fingers_crossed: Nov 22, 2021 at 16:37
  • No prob. If you have follow up questions ask me here. BTW, I realized after writing that I may have taken your use of "fileswap" more literally than you intended...expand('%:p:r') could be used instead of swapname(...) in some places...but it actually has relevance because it relates to the whole "how do you make a path into a unique filename" thing...so I decided to leave it as is.
    – B Layer
    Nov 22, 2021 at 16:49
  • Um, expand('%:p'), that is...there's no .swp extension to deal with in this case.
    – B Layer
    Nov 22, 2021 at 17:03

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.