koturnの日記

転職したい社会人1年生の技術系日記

Vimでルートユーザとして保存する

rootユーザでVimを起動したり, sudoeditVimを起動しなかった場合,権限の無いファイルを編集後,保存しようとしても保存できない. 割とあるあるなことだと思う. (特にVimに閉じこもる人にとっては)

そんなとき,

:w !sudo tee > /dev/null %

と実行することで,ルートユーザとして保存できる. これはよく紹介されている手法で,書籍「実践Vim 思考のスピードで編集しよう! 」でも紹介されている. 簡単にググっただけでも,

のように数多くの記事で紹介されている. 上で紹介した記事や,人の.vimrcでよく見掛けるのが,

cnoremap w!! w !sudo tee > /dev/null %

cabbrev w!! w !sudo tee > /dev/null %

という設定だが,個人的にはコマンドにまとめておく方が好きである.

if executable('sudo')
  function! s:save_as_root(bang, filename) abort
    execute 'write' . a:bang '!sudo tee > /dev/null' (a:filename ==# '' ? '%' : a:filename)
  endfunction
else
  function! s:save_as_root(bang, filename) abort
    echoerr 'sudo is not supported in this environment'
  endfunction
endif
command! -bar -bang -nargs=? -complete=file SudoWrite  call s:save_as_root('<bang>', <q-args>)

これを, w[rite] コマンドと同じように, :SudoWrite と実行するとよい. なお,コマンドが呼び出すのはたった1行の関数なので,わざわざ関数を作る必要はないかもしれない.

if executable('sudo')
  command! -bar -bang -nargs=? -complete=file SudoWrite
        \ execute 'write' . '<bang>' '!sudo tee > /dev/null' (<q-args> ==# '' ? '%' : <q-args>)
else
  command! -bar -bang -nargs=? -complete=file SudoWrite
        \ echoerr 'sudo is not supported in this environment'
endif

正直, bang に関してはあまり意味は無いが,元々の :writebang を取ることができるので,ついでに指定しておいただけだ.

参考