Vim: 在保存时创建父目录

如果我调用 vim foo/bar/somefilefoo/bar不存在,Vim 拒绝保存。

我知道我可以从 Vim 切换到 shell 或者执行 :!mkdir foo/bar,但是我很懒:) 有没有一种方法可以让 Vim 在保存缓冲区时自动做到这一点?

33339 次浏览

基于对我的问题的建议,以下是我的结论:

function WriteCreatingDirs()
execute ':silent !mkdir -p %:h'
write
endfunction
command W call WriteCreatingDirs()

这定义了 :W命令。理想情况下,我希望所有的 :w!:wq:wq!:wall等工作相同,但我不知道是否有可能,如果没有基本上重新实现他们所有的自定义函数。

augroup BWCCreateDir
autocmd!
autocmd BufWritePre * if expand("<afile>")!~#'^\w\+:/' && !isdirectory(expand("%:h")) | execute "silent! !mkdir -p ".shellescape(expand('%:h'), 1) | redraw! | endif
augroup END

注意条件: expand("<afile>")!~#'^\w\+:/'将阻止 vim 为诸如 ftp://*之类的文件创建目录,而 !isdirectory将阻止昂贵的 mkdir 调用。

更新 : 稍微好一点的解决方案,它也检查非空 buftype 并使用 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

我把这个添加到我的 ~/. vimrc

cnoremap mk. !mkdir -p <c-r>=expand("%:h")<cr>/

如果我需要创建我所在的目录,我输入 :mk.,它会用“ !Mkdir-p/path/to/my/file/”,并允许我在调用命令之前查看该命令。

我想我成功地用三句话做到了这一点,结合了其他人对这个答案的看法。

这似乎奏效了:

if has("autocmd")
autocmd BufWritePre * :silent !mkdir -p %:p:h
end

它尝试在保存缓冲区时自动创建文件夹。如果有任何不好的事情发生(比如权限问题) ,它就会关闭,让文件写失败。

如果有人看到任何明显的缺陷,请发表评论。我不是很精通 Vimscript。

编辑: 感谢 ZyX 的笔记

  • 如果文件夹上有空格(显然它们没有被正确转义或其他) ,这将无法工作
  • 或者如果您正在执行伪文件。
  • 或者如果你正在寻找你的 Vimrc。
  • 但是,儿子,这是短暂的。

这段代码 将提示您使用 :w创建目录,或者只使用 :w!:

augroup vimrc-auto-mkdir
autocmd!
autocmd BufWritePre * call s:auto_mkdir(expand('<afile>:p:h'), v:cmdbang)
function! s:auto_mkdir(dir, force)
if !isdirectory(a:dir)
\   && (a:force
\       || input("'" . a:dir . "' does not exist. Create? [y/N]") =~? '^y\%[es]$')
call mkdir(iconv(a:dir, &encoding, &termencoding), 'p')
endif
endfunction
augroup END