Vim: Creating parent directories on save
If I invoke vim foo/bar/somefile
but foo/bar
don't already exist, Vim refuses to save.
I know I could switch to a shell or do :!mkdir foo/bar
from Vim but I'm lazy :)
Is there a way to make Vim do that automatically when it saves the buffer?
Solution 1:
augroup BWCCreateDir
autocmd!
autocmd BufWritePre * if expand("<afile>")!~#'^\w\+:/' && !isdirectory(expand("%:h")) | execute "silent! !mkdir -p ".shellescape(expand('%:h'), 1) | redraw! | endif
augroup END
Note the conditions: expand("<afile>")!~#'^\w\+:/'
will prevent vim from creating directories for files like ftp://*
and !isdirectory
will prevent expensive mkdir call.
Update: sligtly better solution that also checks for non-empty buftype and uses mkdir()
:
function s:MkNonExDir(file, buf)
if empty(getbufvar(a:buf, '&buftype')) && a:file!~#'\v^\w+\:\/'
let dir=fnamemodify(a:file, ':h')
if !isdirectory(dir)
call mkdir(dir, 'p')
endif
endif
endfunction
augroup BWCCreateDir
autocmd!
autocmd BufWritePre * :call s:MkNonExDir(expand('<afile>'), +expand('<abuf>'))
augroup END
Solution 2:
Based on the suggestions to my question, here's what I ended up with:
function WriteCreatingDirs()
execute ':silent !mkdir -p %:h'
write
endfunction
command W call WriteCreatingDirs()
This defines the :W
command. Ideally, I'd like to have all of :w!
, :wq
, :wq!
, :wall
etc work the same, but I'm not sure if it's possible without basically reimplementing them all with custom functions.