1597

多くの人は、sudo で vim を開くのを忘れた場合でも、ルート権限が必要なファイルに書き込むことができるコマンドを見たことがあるでしょう。

:w !sudo tee %

問題は、ここで何が起こっているのか正確にはわかりません。

私はすでにこれを考え出しました: wこれのためです

                                                        *:w_c* *:write_c*
:[range]w[rite] [++opt] !{cmd}
                        Execute {cmd} with [range] lines as standard input
                        (note the space in front of the '!').  {cmd} is
                        executed like with ":!{cmd}", any '!' is replaced with
                        the previous command |:!|.

そのため、すべての行が標準入力として渡されます。

この!sudo tee部分はtee管理者権限で呼び出します。

すべてが理にかなっているために、%はファイル名を ( のパラメーターとしてtee) 出力する必要がありますが、この動作に関するヘルプの参照が見つかりません。

tl;dr誰かがこのコマンドを分析するのを手伝ってくれませんか?

4

9 に答える 9

1814

:w !sudo tee %...

%「現在のファイル」を意味します

eugene yが指摘したように、%実際には「現在のファイル名」を意味します。これはtee、上書きするファイルを知るために渡されます。

(置換コマンドでは、少し異なります。:help :%示されているように、 equal to 1,$ (the entire file)(これがファイル名に評価されないことを指摘してくれた @Orafu に感謝します)。たとえば、 「現在のファイルで、の出現箇所を で置換します。」を:%s/foo/bar意味します。を入力する前にいくつかのテキストを入力すると、強調表示された行が置換範囲として置き換えられることがわかります。)foobar: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で作成した図)

詳細については、teeman ページを参照してください。

ハックとしてティー

あなたの質問が説明する状況では、それが行うことの半分を無視しているため、使用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部分は、標準出力を明示的に破棄します。なぜなら、前述したように、別のパイプ コマンドに何も渡す必要がないからです。

于 2011-08-16T12:49:09.663 に答える
106

実行されたコマンド ラインで%は、現在のファイル名を表します。これについては、次のドキュメントに記載されてい:help cmdline-specialます。

In Ex commands, at places where a file name can be used, the following
characters have a special meaning.
        %       Is replaced with the current file name.

すでにわかっているよう:w !cmdに、現在のバッファーの内容を別のコマンドにパイプします。標準入力をtee1 つまたは複数のファイルにコピーし、標準出力にもコピーします。したがって、root である間:w !sudo tee % > /dev/null、現在のバッファの内容を現在のファイルに効果的に書き込みます。これに使用できる別のコマンドは次のとおりです。dd

:w !sudo dd of=% > /dev/null

ショートカットとして、このマッピングを に追加できます.vimrc:

" Force saving files that require root permission 
cnoremap w!! w !sudo tee > /dev/null %

上記を使用:w!!<Enter>して、ファイルをルートとして保存するために入力できます。

于 2010-04-08T14:45:49.440 に答える
20

:w- ファイルを書き込みます。

!sudo- シェル sudo コマンドを呼び出します。

tee- write (vim :w) コマンドの出力が、tee を使用してリダイレクトされました。% は現在のファイル名、つまり /etc/apache2/conf.d/mediawiki.conf です。つまり、tee コマンドは root として実行され、標準入力を受け取り、それを % で表されるファイルに書き込みます。ただし、これによりファイルを再度リロードするように求められます (L を押して vim 自体の変更をロードします)。

チュートリアル リンク

于 2011-06-04T06:02:49.050 に答える
8

「ファイルを開くときに書き忘れた」問題sudoに対する別のアプローチを提案したいと思います。

を受け取って入力する代わりに、ファイルpermission denied所有者が.:w!!vimsudo vimroot

これは簡単に実装できます (もっと洗練された実装があるかもしれません。私は明らかに bash の第一人者ではありません)。

function vim(){
  OWNER=$(stat -c '%U' $1)
  if [[ "$OWNER" == "root" ]]; then
    sudo /usr/bin/vim $*;
  else
    /usr/bin/vim $*;
  fi
}

そして、それは本当にうまく機能します。

これは-bashよりも - 中心のアプローチvimなので、誰もが好むとは限りません。

もちろん:

  • 失敗するユースケースがあります (ファイルの所有者はroot必要ありませんがsudo、関数はとにかく編集できる場合)
  • 読み取り専用ファイルに使用する場合は意味がありませんvim(私に関する限り、tailまたはcat小さなファイルに使用します)

しかし、これにより、開発者のユーザー エクスペリエンスが大幅に向上することがわかりましbash。:-)

于 2018-02-28T18:21:56.837 に答える