Як зберегти файл у каталозі, який ще не існує?


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>

Тут я використовував %замість цього <afile>, оскільки це дійсно лише з автокоманди ( %відноситься до поточно активного буфера, який би не працював, :waнаприклад; <afile>посилається на ім'я файлу буфера, який запускає autocmd).

Ви також можете попросити підтвердження, перш ніж писати каталог, якщо хочете. Дивіться це запитання для більш детальної інформації: Як я можу зупинити Vim від написання файлу в автокоманді BufWritePre?


Вищенаведений фрагмент створить каталог під час першого запису ( :w). Ви можете, якщо хочете, також створити каталог під час першого відкриття (тобто відразу після введення vim ...), використовуючи BufNewFileautocmd замість BufWritePre.


Існує також плагін під назвою auto_mkdir, який фактично такий же, як і вище.

На цій сторінці є дещо розширений фрагмент, який також запитує, чи ви хочете спершу створити каталог, який деякі можуть вважати корисним. Він також перетворює ім'я файлу кодування перед його написанням:

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

Я не впевнений, чи це насправді потрібно, але якщо ви багато змішуєте кодування і отримуєте дивні назви файлів, ви можете спробувати.


Я все це переклав у auto_mkdir2.vimплагін для легшого встановлення.


3

Я можу порекомендувати плагін Vim від Тіма Попа під назвою vim-eunuch, який визначає багато надзвичайно корисних команд, коли ви працюєте над UNIX / Linux з Vim (ознайомтеся з його особливостями !).

Скажімо, ви відкрили 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 в і відповіді Деміена POLLET в ).


1

Інший спосіб за допомогою ванілі Vim (без додаткових конф або плагінів). у 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>моїми заявами про імпорт.
  2. що saveas«залишає позаду» (якщо буде) прихований буфер в кінці списку буферів. Я не впевнений, що це поведінка держави, якою користуються всі випадки vim / nvim.
  3. Інші FYI: Я використовую NVIM на 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
    
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.