如何将文件保存在尚不存在的目录中?


35

假设我启动Vim编辑尚未创建的目录中的新文件:

vim nonExisitingDirectory/newFile.txt

Vim会很高兴地向我显示一个空缓冲区,我可以开始编写新文件了。但是,当我想将文件写入磁盘时,出现此错误:

E212: Can't Open file for writing.

我认为这是因为该目录尚不存在。有没有办法强迫Vim为我创建目录?

Answers:


37

据我所知,目前尚无设置或类似设置。但是并不是所有的东西都丢失了,我们当然可以使用 BufWritePre自动命令。
这是在将缓冲区写入磁盘之前执行的。因此,如果目录尚不存在,我们可以在该目录中创建目录。

例如:

augroup Mkdir
  autocmd!
  autocmd BufWritePre *
    \ if !isdirectory(expand("<afile>:p:h")) |
        \ call mkdir(expand("<afile>:p:h"), "p") |
    \ endif
augroup END
  • 我们首先使用来检查目录是否存在isdirectory,否则mkdir给出错误。
  • <afile>指我们要保存的文件;:p是一个修饰符,用于将其扩展为完整路径名(而不是相对路径),并:h删除最后一个路径部分(文件)。
  • 然后,mkdir()如果需要,我们会致电。我们需要p标记来mkdir()建立所有父目录(例如nonexistent/more_nonexisting/file

当然,您也可以mkdir()从Vim命令行运行命令,或将其绑定到按键绑定,即:

nnoremap <Leader>m :call mkdir(expand("%:p:h"), "p")<CR>

在这里,我使用%代替<afile>,因为它仅在自动命令中有效(%指的是当前活动的缓冲区,:wa例如,不适用于<afile>该缓冲区;指的是触发au​​tocmd的缓冲区的文件名)。

如果需要,还可以在写入目录之前要求确认。有关更多详细信息,请参见此问题:如何阻止Vim在BufWritePre自动命令中写入文件?


上面的代码段将在首次写入(:w)时创建目录。如果需要,您也可以在首次打开目录时(即在键入后vim ...)通过使用BufNewFileautocmd而不是来创建目录BufWritePre


还有一个名为auto_mkdir的插件,实际上与上述插件相同。

在此页面上, 有一个稍微扩展的代码段,该代码段还会询问您是否要首先创建目录,有些人可能会认为这很有用。在编写之前,它还转换了编码的文件名:

call mkdir(iconv(expand("%:p:h"), &encoding, &termencoding), 'p')

我不确定是否确实需要这样做,但是如果您混合使用多种编码并获取奇怪的文件名,则可以尝试一下。


我将以上所有内容都放在了一个auto_mkdir2.vim插件中,以便于安装。


3

我可以推荐Tim Pope的vim插件vim-eunuch,该插件定义了在使用Vim的UNIX / Linux上工作时非常有用的命令(请查看其功能!)。

假设您使用打开vim,vim this/is/a/test而这些目录之前都不存在。只需运行:Mkdir!<CR>,vim-eunuch即可为您创建它们(使用mkdir -p),因此您现在可以使用保存文件:w<CR>


2

使用:W创建文件和它的父目录:

function! s:WriteCreatingDirs()
  let l:file=expand("%")
  if empty(getbufvar(bufname("%"), '&buftype')) && l:file !~# '\v^\w+\:\/'
    let dir=fnamemodify(l:file, ':h')
    if !isdirectory(dir)
      call mkdir(dir, 'p')
    endif
  endif
  write
endfunction
command! W call s:WriteCreatingDirs()

(添加到您的中vimrc。基于Zyx的答案Damien Pollet的答案的组合)。


1

香草Vim的另一种方式(无需额外的conf或插件)。在Vim中:

:!mkdir -p /folder/you/want/
:w  #save file

要么

$ vim /folder/you/want/myfile.conf
$ ctrl+z # switch to the terminal then create the folders
$ mkdir -p /folder/you/want/
$ fg # return to Vim
$ :w  #save file

1

我希望提供一个基于上述答案的版本,以进一步简化工作流程。我经常在各种项目结构中创建新文件。这种调整将为我节省大量时间。

我可以想到两个依赖项:

  1. 我设置autochdir它是因为它对<C-x><C-f>我的import语句如何起作用。
  2. 缓冲区列表末尾saveas“后退”(如果您愿意)的隐藏缓冲区。我不确定这是否是所有vim / nvim实例都喜欢的状态行为。
  3. 仅供参考:我在Mac OS上使用NVIM

    " Auto magically Mkdir
    " ====================
    
    autocmd BufWritePre * call MkDir()
    
    function! MkDir()
       if !isdirectory(expand("<afile>:p:h"))
          let confirmation=confirm("Create a new directory?", "&Yes\n&No")
          if confirmation == 1
             call mkdir(expand("<afile>:p:h"), "p")
             lcd %:p:h
             saveas %:t
             echom "Created a new directory:" expand("<afile>:p:h")
             let buf_del = bufnr("$")
             exe "bd" . buf_del
          endif
          redraw
       endif
    endfunction
    
    " Conditionaly create the parent directory when writing to disk
    " <afile> refers to the file we are saving
    " :p is a modifier that expands to full filename
    " :h is a modifier that removes the file from full filename
    " :t is a modifier that generates the filename with extension
    " "p" is the flag that will create all the parent directories
    
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.