Bagaimana cara saya menyimpan file di direktori yang belum ada?

35

Misalkan saya memulai Vim untuk mengedit file baru di direktori yang belum dibuat:

vim nonExisitingDirectory/newFile.txt

Vim dengan senang hati akan menunjukkan kepada saya buffer kosong dan saya dapat mulai menulis file baru saya. Tetapi ketika saya ingin menulis file ke disk saya mendapatkan kesalahan ini:

E212: Can't Open file for writing.

Saya kira ini karena direktori belum ada. Apakah ada cara untuk memaksa Vim membuat direktori untuk saya?

DeltaLima
sumber

Jawaban:

37

Sejauh yang saya tahu tidak ada pengaturan atau semacamnya untuk melakukan ini. Tapi tidak semua hilang, kita tentu saja bisa menggunakan BufWritePreautocommand.
Ini dijalankan sebelum buffer ditulis ke disk. Jadi kita dapat membuat direktori di sana jika belum ada.

Sebagai contoh:

augroup Mkdir
  autocmd!
  autocmd BufWritePre *
    \ if !isdirectory(expand("<afile>:p:h")) |
        \ call mkdir(expand("<afile>:p:h"), "p") |
    \ endif
augroup END
  • Kami pertama-tama memeriksa apakah direktori tersebut ada isdirectory, atau mkdirmemberikan kesalahan.
  • <afile>merujuk ke file yang kami coba simpan; :padalah pengubah untuk memperluasnya ke pathname lengkap (bukan relatif), dan :hmenghapus komponen path terakhir (file).
  • Kami kemudian memanggil mkdir()jika diperlukan. Kita perlu pbendera untuk mkdir()membuat semua direktori orang tua (mis. Dalam kasus nonexistent/more_nonexisting/file.

Anda bisa, tentu saja, juga menjalankan mkdir()perintah dari Vim commandline, atau mengikatnya ke keybind, yaitu:

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

Di sini saya menggunakan %alih-alih <afile>, karena itu hanya berlaku dari dalam autocommand ( %merujuk ke buffer yang saat ini aktif, yang tidak akan berfungsi dengan :wamisalnya; <afile>merujuk pada nama file buffer yang memicu autocmd).

Anda juga dapat meminta konfirmasi sebelum menulis direktori jika Anda mau. Lihat pertanyaan ini untuk detail lebih lanjut: Bagaimana saya bisa menghentikan Vim dari menulis file dalam perintah otomatis BufWritePre?


Cuplikan di atas akan membuat direktori pada write pertama ( :w). Anda bisa, jika mau, juga membuat direktori ketika pertama kali membukanya (yaitu setelah mengetik vim ...) dengan menggunakan BufNewFileautocmd alih-alih BufWritePre.


Ada juga sebuah plugin bernama auto_mkdir yang secara efektif sama dengan yang di atas.

Pada halaman ini ada cuplikan yang sedikit diperluas yang juga menanyakan apakah Anda ingin membuat direktori terlebih dahulu, yang mungkin dianggap bermanfaat oleh beberapa orang. Ini juga telah mengonversi nama file pengodean sebelum menulisnya:

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

Saya tidak yakin apakah ini benar-benar diperlukan, tetapi jika Anda mencampur enkode banyak dan mendapatkan nama file yang aneh, Anda bisa mencobanya.


Saya meletakkan semua hal di atas dalam sebuah auto_mkdir2.vimplugin untuk instalasi yang lebih mudah.

Martin Tournoij
sumber
3

Saya dapat merekomendasikan plugin vim dari Tim Pope bernama vim-kasim yang mendefinisikan banyak perintah yang sangat berguna ketika pekerjaan Anda di UNIX / Linux dengan Vim (lihat fitur-fiturnya !).

Katakanlah Anda membuka vim dengan vim this/is/a/testdan tidak ada direktori ini ada sebelumnya. Jalankan saja :Mkdir!<CR>dan vim-kasim membuatnya untuk Anda (dengan mkdir -p), jadi Anda sekarang dapat menyimpan file Anda :w<CR>.

cbaumhardt
sumber
2

Gunakan :Wuntuk membuat file dan direktori induknya:

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()

(Tambahkan ke vimrc. Berdasarkan kombinasi jawaban Zyx dan jawaban Damien Pollet ).

Tom Hale
sumber
1

Cara lain dengan vanim Vim (tanpa conf atau plugin tambahan). di Vim:

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

atau

$ 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
xaa
sumber
1

Saya berharap dapat berkontribusi versi yang dibangun di atas jawaban di atas untuk merampingkan alur kerja lebih banyak lagi. Saya sering membuat file baru dalam berbagai struktur proyek. Tweak ini akan menghemat banyak waktu.

Ada dua dependensi yang dapat saya pikirkan:

  1. Saya menetapkan autochdirkarena cara kerjanya <C-x><C-f>untuk pernyataan impor saya.
  2. yang saveas"daun belakang" (jika Anda mau) buffer tersembunyi di akhir dari daftar penyangga. Saya tidak yakin apakah itu adalah perilaku negara yang dinikmati semua instance vim / nvim.
  3. FYI Lainnya: Saya menggunakan NVIM di Mac OS

    " 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
    
Edmund's Echo
sumber