Consider an answer to How do I install a plugin in Vim/vi?:

call plug#begin('~/.vim/plugged')
" For MS Windows, this is probably better:
"call plug#begin('~/vimfiles/plugged')

And more generally, things which go into '~/.vim' under Linux should go into '~/vimfiles' under Windows. How can I refer to the correct directory in my .vimrc (or in other Vimscript files, I guess)?

  • 1
    .vim works on Windows as well as on Linux, however it might be hard to actually create that folder, but I have used that as my main configuration folder for at least 10 years Commented Feb 16, 2018 at 21:23
  • @ChristianBrabandt are you sure about .vim on windows? I have just renamed vimfiles to .vim and my config is not applied both on gVim and vim in cmd.
    – Maxim Kim
    Commented Nov 26, 2020 at 8:53
  • I might not. I thought it worked, but perhaps I did configure my system differently. I do not remember Commented Nov 26, 2020 at 9:19
  • 1
    Also note that with vim-plug you can simply use call plug#begin() with no arguments and it will default to a plugged directory under the appropriate subdirectory of your home directory.
    – filbranden
    Commented Nov 28, 2020 at 23:31
  • On Windows, calling vim from git-bash will use .vim while starting gVim or calling vim.exe from cmd will use vimfiles. So it may work depending on which executable you run from where.
    – Friedrich
    Commented Jan 10 at 7:04

7 Answers 7


Another possible solution is to test the features of your installation:

if has('win32')
    let $MYPLUGDIRECTORY = "~/vimfiles/plugged"
    let $MYPLUGDIRECTORY = "~/.vim/plugged"

call plug#begin($MYPLUGDIRECTORY)

It has the advantage to let you mess with your rtp setup. For example, if for whatever reason the first directory in rtp is not $HOME/.vim/ you will not break your plugins.

An important note from the doc, has('win32') works for both 32 and 64 bits systems:

win32           Win32 version of Vim (MS-Windows 95 and later, 32 or 64 bits)

You can read more at:


An answer I found, but not sure whether it's optimal or correct in all circumstances: split(&rtp, ',')[0] . '/plugged'

  • This is IMO the best answer. In fact, it's what vim-plug uses if plug#begin() is called with no arguments. It covers both the cases of Windows vs. Unix and also Vim vs. NeoVim.
    – filbranden
    Commented Nov 28, 2020 at 23:29
  • Not perfect though. What if the first entry of split(&rtp, ',') was not found?.
    – mattalxndr
    Commented May 31, 2021 at 0:11

I create a symlink from .vim to vimfiles in the Windows Command prompt, and then use just .vim throughout my .vimrc.

mklink /D .vim %HOMEDRIVE%%HOMEPATH%\vimfiles

(Actually, what I do is link both vimfiles and .vim to a git repository, elsewhere, but this should work fine too.)

  • You don't actually need that link. Vim on Windows will also use ~/.vim Commented Feb 17, 2018 at 8:27
  • @ChristianBrabandt Doesn't work for me. I just tried deleting my vimfiles symlink, and on running Vim I got a number of errors: "Unknown function: (autoload function)", "Cannot find color scheme", etc. Then, after stating up, 'rtp' contains vimfiles and does not contain .vim. N.B. I didn't try renaming my _vimrc: any chance the code looks for that first and then uses vimfiles or .vim based on the name?
    – Rich
    Commented Feb 19, 2018 at 9:19
  • Hm strange, don't know why it wouldn't work. I remember having used that several times in the past. Commented Feb 19, 2018 at 10:38

I use the following (from my lh-vim-lib library plugin):

function! lh#path#vimfiles() abort
  let re_HOME = lh#path#to_regex($HOME.'/')
  let re_LUCHOME = exists('$LUCHOME') ? '\|'.lh#path#to_regex($LUCHOME.'/'): ''
  let what = '\%('.re_HOME.re_LUCHOME.'\)'.'\(vimfiles\|.vim\|.config[/\\]nvim\)'
  " Comment what
  let z = lh#path#find(&rtp,what)
  return z

function! lh#path#to_regex(path) abort
  let regex = substitute(a:path, '[/\\]', '[/\\\\]', 'g')
  return regex

function! lh#path#find(paths, regex) abort
  let paths = (type(a:paths) == type([]))
        \ ? (a:paths)
        \ : split(a:paths,',')
  call filter(paths, 'match(v:val, a:regex) != -1')
  let shortest = lh#list#arg_min(paths, function('len'))
  return empty(paths) ? '' : paths[shortest]

function! lh#list#arg_min(list, ...) abort
  if empty(a:list) | return -1 | endif
  if a:0 > 0
    let Transfo = a:1
    let list = map(copy(a:list), '[Transfo(v:val), v:key]')
    let list = map(copy(a:list), '[v:val, v:key]')
  let res = [list[0]]
  call map(list[1:], 'add(res, v:val[0] < res[-1][0] ? v:val : res[-1])')
  return res[-1][1]

It's somehow overkill, but at least it permits me to share accounts (in that case I put my configuration stuff in ~/luc and I set $LUCHOME -- yeah this is really bad, but sometimes very bad practices are enforced), and it works with vim (windows and *nix), and neovim apparently, and it supports any value for shellslash. It doesn't expect ~/{.vim,vimfiles}/ to be the first directory in &rtp either.

  • 1
    It's somehow overkill yeah "somehow" ;-) I'm honestly always amazed by your vimscript skills and all the helper functions you've created!
    – statox
    Commented Feb 16, 2018 at 14:47
  • 1
    Thanks :) Otherwise, these helper functions are the result of 20ish years of vimscripting on a wide range of machines (solaris, linux, XP, win10...) and with sometimes odd constraints. Commented Feb 16, 2018 at 14:57
  • 1
    Yeah browsing the github repo of your lib clearly shows that you didn't start yesterday! It's cool to have such veteran vimmer on this site :)
    – statox
    Commented Feb 16, 2018 at 15:04
  • 1
    Vim 8 adds type(v:t_list) as a replacement for type([]). (I know Luc is maintaining b/w compat so this is just a general fyi.)
    – B Layer
    Commented Mar 19, 2018 at 4:59
  • Thanks @BLayer. I missed this information. But as you guessed, I've to wait for 5-10years before I'll be able to use it. Commented Mar 19, 2018 at 10:38

You can read the path of $MYVIMRC (which points to your .vimrc):

call plug#begin(fnamemodify($MYVIMRC, ":p:h") . '/bundle')

Just check to see if the directory exists with isdirectory():

if isdirectory(expand('~/.vim/plugged', ':p'))
    call plug#begin('~/.vim/plugged')
    call plug#begin('~/vimfiles/plugged')

For more help see:

:h isdirectory()
:h fnamemodify()
:h expand()
  • Does isdirectorey('~/foobar') actually resolve the ~? I did not expect that and thought it would need an additional expand() call. Commented Feb 16, 2018 at 21:24
  • @ChristianBrabandt, You are correct. I mixed up my function calls. Thank you. Can you use expand() or must we use fnamemodify()? Commented Feb 16, 2018 at 21:51
  • 1
    I think expand() should work Commented Feb 16, 2018 at 21:58

Similar to @Rich's answer, I created a hardlink from my dotfiles git repo (like dotfiles/.vim/vimrc) folder to vimfiles using Powershell:

New-Item -ItemType Junction -Name vimfiles -Value "C:\Users\$env:USERNAME\dotfiles\.vim"

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.