1

I have this in my .vimrc:

set directory=~/.vim/tmp-backup-swapfiles

This directory is read- and writable by me, sensibly enough. It is part of the local filesystem and never inaccessible.

However, vim seems to often ignore this and instead use ~/tmp. I've sometimes thought it does this with files from a remote mounted filesystem, but since I do that much of the time it is hard to tell. Also, there are inconsistencies -- for example, right now I have gvim (7.4.475) open with a local file who's swap turns out to be in ~/tmp and a remote file whose swap is in ~/.vim/tmp-backup-swapfiles. It is easy to see they are both still in play by making a change to the buffer and checking the timestamp. I also have a source and header file from the same location open, but the .hpp.swp is in ~/tmp and the .cpp.swp is in ~/.vim/tmp-backup-swapfiles :\

This gets irritating when I have to clean up for whatever reason, or fail to, and get told there's suddenly a swapfile from last week in play on something I've been editing since. What can I do to force it to just use the one directory specified to ensure there's no confusion?

1

Use

:set dir?

to see which directories are used to store your swap files. If you insist on having just one directory, you could use

set directory=~/.vim/tmp-backup-swapfiles//

Using double trailing slashes in the path tells Vim to create swap files using the whole path of the files being edited to avoid collisions.

1
  • Hmmm -- the output from :set dir? seems inaccurate; right now I get ~/tmp,/var/tmp,/tmp, but there's a .swp file in ~/.vim/tmp-backup-swapfiles that is obviously being used (when I change the buffer, the timestamp on that file is immediately updated). I'll try your suggestion; I'm guessing the first set directory= is to clear any defaults? To clarify further, are you saying that vim only resorts to other directories when I load two files with the same name but different paths?
    – goldilocks
    Oct 15 '15 at 1:26
2

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/*

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.