Làm cách nào để lưu tệp trong thư mục chưa tồn tại?


35

Giả sử tôi bắt đầu Vim để chỉnh sửa một tệp mới trong thư mục chưa được tạo:

vim nonExisitingDirectory/newFile.txt

Vim sẽ vui vẻ chỉ cho tôi một bộ đệm trống và tôi có thể bắt đầu viết tập tin mới của mình. Nhưng khi tôi muốn ghi tập tin vào đĩa thì tôi gặp lỗi này:

E212: Can't Open file for writing.

Tôi đoán điều này là do thư mục chưa tồn tại. Có cách nào để buộc Vim tạo thư mục cho tôi không?

Câu trả lời:


37

Theo như tôi biết thì không có thiết lập hay một số thứ như vậy để làm điều này. Nhưng không phải tất cả đã mất, tất nhiên chúng ta có thể sử dụng chế độ BufWritePretự động.
Điều này được thực hiện trước khi bộ đệm được ghi vào đĩa. Vì vậy, chúng ta có thể tạo thư mục ở đó nếu nó chưa tồn tại.

Ví dụ:

augroup Mkdir
  autocmd!
  autocmd BufWritePre *
    \ if !isdirectory(expand("<afile>:p:h")) |
        \ call mkdir(expand("<afile>:p:h"), "p") |
    \ endif
augroup END
  • Trước tiên chúng tôi kiểm tra xem thư mục có tồn tại isdirectorykhông, nếu không mkdirsẽ báo lỗi.
  • <afile>đề cập đến tập tin chúng tôi đang cố gắng lưu; :plà một sửa đổi để mở rộng nó thành tên đường dẫn đầy đủ (chứ không phải tương đối) và :hloại bỏ thành phần đường dẫn cuối cùng (tệp).
  • Sau đó chúng tôi gọi mkdir()nếu được yêu cầu. Chúng ta cần pcờ mkdir()để tạo tất cả các thư mục cha mẹ (ví dụ: trong trường hợp nonexistent/more_nonexisting/file.

Tất nhiên, bạn cũng có thể chạy mkdir()lệnh từ dòng lệnh Vim hoặc liên kết nó với một keybind, tức là:

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

Ở đây tôi đã sử dụng %thay vì <afile>, vì nó chỉ hợp lệ từ bên trong một autocommand ( %đề cập đến bộ đệm hiện đang hoạt động, :wachẳng hạn như không hoạt động ; <afile>đề cập đến tên tệp của bộ đệm kích hoạt autocmd).

Bạn cũng có thể yêu cầu xác nhận trước khi viết một thư mục nếu bạn muốn. Xem câu hỏi này để biết thêm chi tiết: Làm cách nào tôi có thể ngăn Vim viết một tệp trong chế độ tự động BufWritePre?


Đoạn mã trên sẽ tạo thư mục trong lần ghi đầu tiên ( :w). Bạn có thể, nếu bạn muốn, cũng tạo thư mục khi bạn mở nó lần đầu tiên (tức là ngay sau khi gõ vim ...) bằng cách sử dụng BufNewFileautocmd thay vì BufWritePre.


Ngoài ra còn có một plugin gọi là auto_mkdir , có hiệu quả tương tự như trên.

Trên trang này có một đoạn được mở rộng một chút, nó cũng hỏi bạn có muốn tạo thư mục trước không, một số có thể coi là hữu ích. Nó cũng đã chuyển đổi tên tệp của mã hóa trước khi viết nó:

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

Tôi không chắc chắn nếu điều này thực sự cần thiết, nhưng nếu bạn trộn mã hóa nhiều và nhận được tên tệp kỳ lạ, bạn có thể thử nó.


Tôi đặt tất cả những điều trên trong một auto_mkdir2.vimplugin để cài đặt dễ dàng hơn.


3

Tôi có thể giới thiệu một plugin vim từ Tim Pope có tên là vim-eunuch , định nghĩa nhiều lệnh cực kỳ hữu ích khi bạn làm việc trên UNIX / Linux với Vim (kiểm tra các tính năng của nó !).

Giả sử bạn mở vim với vim this/is/a/testvà không có thư mục nào trong số này tồn tại trước đó. Chỉ cần chạy :Mkdir!<CR>và vim-eunuch tạo chúng cho bạn (với mkdir -p), vì vậy bây giờ bạn có thể lưu tệp của mình với :w<CR>.


2

Sử dụng :Wđể tạo một tệp và các thư mục mẹ của nó:

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

(Thêm vào của bạn vimrc. Dựa trên sự kết hợp giữa câu trả lời của Zyxcâu trả lời của Damien Pollet ).


1

Một cách khác với Vim vani (không có thêm conf hoặc plugin). trong Vim:

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

hoặc là

$ 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

Tôi hy vọng sẽ đóng góp một phiên bản dựa trên các câu trả lời ở trên để hợp lý hóa quy trình công việc hơn thế nữa. Tôi thường tạo các tệp mới trong một loạt các cấu trúc dự án. Tinh chỉnh này sẽ giúp tôi tiết kiệm một lượng thời gian.

Có hai sự phụ thuộc mà tôi có thể nghĩ đến:

  1. Tôi đặt autochdirvì cách nó hoạt động với <C-x><C-f>các báo cáo nhập khẩu của tôi.
  2. các saveas"lá đằng sau" (nếu bạn sẽ) một bộ đệm ẩn tại cuối của danh sách đệm. Tôi không chắc đó có phải là hành vi trạng thái mà tất cả các trường hợp vim / nvim đều thích hay không.
  3. FYI khác: Tôi sử dụng NVIM trên hệ điều hành Mac

    " 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
    
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.