で:w !sudo tee %
...
%
「現在のファイル」を意味します
eugene yが指摘したように、%
実際には「現在のファイル名」を意味します。これはtee
、上書きするファイルを知るために渡されます。
(置換コマンドでは、少し異なります。:help :%
示されているように、 equal to 1,$ (the entire file)
(これがファイル名に評価されないことを指摘してくれた @Orafu に感謝します)。たとえば、 「現在のファイルで、の出現箇所を で置換します。」を:%s/foo/bar
意味します。を入力する前にいくつかのテキストを入力すると、強調表示された行が置換範囲として置き換えられることがわかります。)foo
bar
:s
%
:w
ファイルを更新していません
:w
このトリックの紛らわしい部分の 1 つは、ファイルを変更していると思うかもしれませんが、そうではありません。を開いて変更してfile1.txt
から実行し:w file2.txt
た場合、「名前を付けて保存」になります。file1.txt
は変更されませんが、現在のバッファの内容は に送信されfile2.txt
ます。
の代わりに、シェル コマンドを代用してバッファの内容を受け取るfile2.txt
ことができます。たとえば、コンテンツを表示するだけです。:w !cat
Vim が sudo アクセスで実行されて:w
いない場合、保護されたファイルを変更することはできませんが、バッファーの内容をシェルに渡す場合は、シェル内のコマンドを sudo で実行できます。この場合、 を使用しますtee
。
ティーを理解する
については、コマンドを通常の bash パイピング状況での T 字型パイプとしてtee
描いてください。指定されたファイルに出力を送信し、次のパイプ コマンドでキャプチャできる標準出力にも送信します。tee
たとえば、 ではps -ax | tee processes.txt | grep 'foo'
、プロセスのリストがテキスト ファイルに書き込まれ、に渡されgrep
ます。
+-----------+ tee +------------+
| | -------- | |
| ps -ax | -------- | grep 'foo' |
| | || | |
+-----------+ || +------------+
||
+---------------+
| |
| processes.txt |
| |
+---------------+
( Asciiflowで作成した図)
詳細については、tee
man ページを参照してください。
ハックとしてティー
あなたの質問が説明する状況では、それが行うことの半分を無視しているため、使用tee
はハックです。sudo tee
ファイルに書き込み、バッファの内容を標準出力に送信しますが、標準出力は無視します。この場合、別のパイプ コマンドに何も渡す必要はありません。ファイルを書き込む別の方法として使用しているだけtee
なので、 で呼び出すことができますsudo
。
このトリックを簡単にする
これを に追加して.vimrc
、このトリックを使いやすくすることができます: と入力するだけです:w!!
。
" Allow saving of files as sudo when I forgot to start vim using sudo.
cmap w!! w !sudo tee > /dev/null %
この> /dev/null
部分は、標準出力を明示的に破棄します。なぜなら、前述したように、別のパイプ コマンドに何も渡す必要がないからです。