まだ存在しないディレクトリにファイルを保存するにはどうすればよいですか?


35

Vimを起動して、まだ作成されていないディレクトリ内の新しいファイルを編集するとします。

vim nonExisitingDirectory/newFile.txt

Vimは喜んで空のバッファーを表示し、新しいファイルの書き込みを開始できます。しかし、ファイルをディスクに書き込みたい場合、このエラーが発生します:

E212: Can't Open file for writing.

これは、ディレクトリがまだ存在しないためと思われます。Vimにディレクトリの作成を強制する方法はありますか?

回答:


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>

ここでは、オートコマンド内からのみ有効であるため、%代わりにを使用しました(たとえば、現在アクティブなバッファーを参照します。これは動作しません。autocmdをトリガーするバッファーのファイル名を参照します)。<afile>%:wa<afile>

必要に応じて、ディレクトリを書き込む前に確認を求めることもできます。詳細については、この質問を参照してください:VimがBufWritePre自動コマンドでファイルを書き込むのを停止するにどうすればよいですか?


上記のスニペットは、最初の書き込み時にディレクトリを作成します(:w)。必要に応じvim ...て、のBufNewFile代わりにautocmd を使用して、ディレクトリを最初に開いたときに(つまり、を入力した直後に)ディレクトリを作成することもできますBufWritePre


上記と実質的に同じauto_mkdirと呼ばれるプラグインもあります。

このページ には、ディレクトリを最初に作成するかどうかを尋ねる少し拡張されたスニペットがあります。また、書き込む前にエンコーディングのファイル名を変換します:

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

ただし、これが実際に必要かどうかはわかりませんが、エンコードを多く混ぜて、奇妙なファイル名を取得した場合は、試してみてください。


簡単にインストールできるように、上記のすべてをauto_mkdir2.vimプラグインに入れました。


3

Tim Popeのvim-eunuchというvimプラグインをお勧めします。これは、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()

(に追加します。Zyxの回答Damien Polletの回答vimrc組み合わせに基づきます)。


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

上記の回答に基づいて構築されたバージョンを提供して、ワークフローをさらに合理化したいと考えています。多くの場合、さまざまなプロジェクト構造内で新しいファイルを作成しています。この調整により、時間を大幅に節約できます。

私が考えることができる2つの依存関係があります:

  1. インポートステートメントautochdirでの動作方法のために設定しました<C-x><C-f>
  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
    
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.