I think it's best to address this problem in two parts: (1) how to specify a single directory for swap files and (2) why it seems like Vim is ignoring this value sometimes.
1. Setting a Single Directory for Swap Files
As indicated by ryuichiro, set the VIM variable directory
to a single path to place all swap files in one directory:
set directory=~/.vim/swap//
2. Why Does Vim Sometimes Ignore This Value?
It is possible for other Vim configuration components (e.g., autocmds specified in a system wide vimrc) to overwrite the user specified directory
value.
Open a file with Vim and verbosely query the value of the directory
option (i.e., :verbose set directory?
). If the value does not match what you are expecting, then you can use the "last set from" path provided by the verbose output to track down the offending code.
If you're having trouble evoking the overwrite behavior (i.e., the overwrite is sporadic and you don't know how to trigger it), then you can make use of the OptionSet
autocmd event like so:
autocmd OptionSet directory verbose set directory?
If your version of Vim does not support the OptionSet
event, then the following function and autocmd can be used instead:
function! DetectOverwrittenOption()
if expand("~/.vim/swap//") !=# expand(&directory)
echo "Overwritten option value detected!"
verbose set dir?
endif
endfun
autocmd BufReadPost * call DetectOverwrittenOption()
A Concrete Example
The Problem
While working with Vim 7.4 on a CentOS 7 machine I noticed that directory
value specified in my user vimrc (~/.vimrc
) was being overwritten with the value directory=~/tmp,/var/tmp,/tmp
.
Isolating the Cause
Running the command :verbose set directory?
resulted in the following output:
directory=~/tmp,/var/tmp,/tmp
Last set from /etc/vimrc
This is listed as the system wide vimrc in the output of the :version
command. The vimrc help documentation (i.e., :help vimrc
) states that the system wide vimrc is used for initializations before loading the user vimrc.
The system wide vimrc I encountered can be viewed on the CentOS Vim tree (link), but I have included the offending lines of code below:
" don't write swapfile on most commonly used directories for NFS mounts or USB sticks
autocmd BufNewFile,BufReadPre /media/*,/run/media/*,/mnt/* set directory=~/tmp,/var/tmp,/tmp
I was able to confirm the presence of these autocmds from the output of the command :autocmd
:
redhat BufNewFile
/media/* set directory=~/tmp,/var/tmp,/tmp
/run/media/*
set directory=~/tmp,/var/tmp,/tmp
/mnt/* set directory=~/tmp,/var/tmp,/tmp
...
redhat BufReadPre
/media/* set directory=~/tmp,/var/tmp,/tmp
/run/media/*
set directory=~/tmp,/var/tmp,/tmp
/mnt/* set directory=~/tmp,/var/tmp,/tmp
I knew my user directory was on a NFS share and resolved the path with readlink -f .
:
/mnt/misc-home/Users/iandinwoodie
It's clear that editing any file under my user directory will match the /mnt/*
pattern resulting in an overwrite of my user specified directory
value. As a sanity check, I opened a file with a path that would not match (e.g., vim /etc/foo.txt
) and observed that my user specified value had not been overwritten.
My Solution
It's clear from the troubleshooting above that the issue is platform specific; therefore, there might not be a "one size fits all" solution. For the scenario described above, I wanted to remove the autocmd behavior for paths matching /mnt/*
while retaining the behavior for paths matching /media/*
and /run/media/*
. To achieve this, I added the following code to my vimrc:
autocmd! redhat BufNewFile,BufReadPre /mnt/*