xargsでVimを呼び出した後、ターミナルが停止しました


30

私は時々xargs、次のようにVimを呼び出してみました:

find . -name '*.java' | xargs vim

…どの種類の作品:

  1. Vimが起動すると、次の警告が短時間点滅します。

    Vim: Warning: Input is not from a terminal
    
  2. 編集は機能します— 期待どおりに:filesすべての.javaファイルを正しく列挙します。
  3. 保存して終了できます。

しかし、Vimを終了した後、私の端末は停止します:

  • シェルプロンプトで入力した内容はエコーされません。
  • キャリッジリターンはまったく表示されず、改行のみが表示される場合があります。

これはreset(1)、端末を再初期化するコマンドを発行するまで続きます。

これはVimのバグですか、それともそのような端末と対話する理由について、より満足のいく説明がありますか?LinuxおよびさまざまなUnicesでVimバージョン7.3(バージョンは重要ではないようです)までVimで発生するのを見てきました。

私は1つの回避策、すなわちを知っていますvim $(find . -name '*.java')。私の主な質問ではありませんが、他の回避策も歓迎します。


このサイトをできるだけ多くの質問で埋めたいと思っていますが、その質問は長年にわたってSO / SUなどで何十回も回答されています。Vimやブレークで使用できないxargsダミーstdinを使用していますその後すべて。
ロメイン

1
@romainl私はそれらのサイトで活動していません、そして、それがそこで尋ねられるのを見たことがありません—正直。
200_success

関連:superuser.com/questions/336016/…-おそらく、誰かがトップアンサーを素晴らしいアンサーに凝縮できるでしょう。
ムル

2
すばらしい質問です-これは私に何度も起こりました。また、他のSOサイトは使用していません。vim関連の場合は、ここで見つけたいと思います。
craigp

回答:


21

これは、vimが呼び出され、ターミナルの代わりに前のパイプラインの出力に接続され、異なる予期しない入力(NULなど)を受け取ったときに発生します。を実行しても同じことが起こります:vim < /dev/nullresetこの場合のコマンドが役立ちます。これは、スーパーユーザーの悲しみによってうまく説明できます

find編集するファイル名を渡すために使用している場合は、必要ありません。例でxargs-exec、を使用します。

find . -name '*.java' -exec vim {} +

あなたが使用したい場合はxargs、UNIX / MacOSであなたが使用する必要があります-oように、パラメータを:

find . -name '*.java' | xargs -o vim

-oコマンドを実行する前に、子プロセスで標準入力を/ dev / ttyとして再度開きます。これは、xargsで対話型アプリケーションを実行する場合に便利です。

または:

find . -name "*.java" -type f -print0 | xargs -o -0 vim

注:-print0/ -0を使用すると、空白を含むファイル名がサポートされます。


find+ BSDxargs

Unix / macOSでは、次の回避策を試すことができます。

find . -name '*.java' | xargs -J% sh -c 'vim < /dev/tty $@'

次のようなコマンド置換構文を使用することもできます。

vim $(find . -name '*.java')
vim `find . -name '*.java`

あるいは、次の例のように、ttyの割り当てを強制するparallel代わりにGNU を使用しますxargs

find . -name '*.java' | parallel -X --tty vi

注:parallelUnix / OSXでは、パラメーターが異なり、ttyをサポートしていないため機能しません。

ウェル(などの他の多くの人気のあるコマンドは、仮想端末の割り当てを提供-tssh)、その助けをチェック。

他の提案は、使用することです:

関連:


私のGNUにxargsはありません-J。これは、GNUバージョンにはないMacOS(BSD)オプションのようです。
追って通知があるまで一時停止します。

12

回避策の提案:バッファをファイルシステムナビゲータとして使用する

このvim -コマンドを使用して、stdinからパスのリストを読み取ります。Vim :help --がこれを説明しています:1

stdinから読み取られたテキストで満たされた新しいバッファーの編集を開始します。通常stdinから読み込まれるコマンドは、stderrから読み込まれます。例:

find . -name "*.c" -print | vim -

その後、gfまたはCtrl-wCtrl-fを使用して、それぞれ同じバッファ内または新しい分割ウィンドウ内のファイルに移動できます。

回避策の提案:引数リスト

もう1つの優れた方法は、Vimの引数リストを使用することです。この:argadd **/*.javaコマンドは、現在のディレクトリ内で見つかったすべてのjavaファイルを再帰的にVimの引数リストに追加します。その後、:next:prevを使用して、ファイル間を移動できます。


1 1 つ目-はコマンドラインオプションのヘルプを検索することをVimに指示し、2つ目は実際に検索するコマンドラインフラグです。:help help-contextこのようなその他のトリックをお読みください。


8

に加えてreset、あなたは試すことができます:

stty sane

また、端末が再び使用可能になります。

説明についてはこちらをご覧ください。どういうわけか、これはvimの誤動作と見なすことができます。少なくともNeovimには現時点ではこの問題はありません。


これは質問に正確に答えるわけではありませんが、私を助けてくれたので、+ 1。
モニカiamnotmaynard

これは私の質問に答えます;)OPをもっと読んだ後、私resetもそうすべきだと思います。
スリダールサルノバト

1

理由は、にxargs設定stdinするの/dev/nullに対し、に設定するvim必要stdinがあること/dev/ttyです。


BSD xargs(Macなど)ソリューション:

echo -e 'file1\nfile2' | xargs -o vim

-oセットstdinxargの子プロセスの(vimこの場合)へdev/tty


GNU xargs(Linuxなど)ソリューション:

GNUにxargs-oオプションがありません。代わりに、より複雑な回避策を使用する必要があります。(注:末尾のzero文字列を持つことは非常に重要です。忘れないでください。)

echo -e 'file1\nfile2' | xargs bash -c '</dev/tty vim "$@"' zero

エイリアスにすることもできます:

alias vimin='xargs bash -c '\''</dev/tty vim "$@"'\'' zero'
echo -e 'file1\nfile2' | vimin

GNU xargsソリューションの詳細な説明

ステップごとに分解してみましょう。

echo -e 'file1\nfile2' | xargs bash -c '</dev/tty vim "$@"' zero

1. xargs単にstdin文字列の最後にを追加するので、これxargsを実行します:

    bash -c '</dev/tty vim "$@"' zero file1 file2

2.の形式はbash -cですbash -c 'COMMAND_STRING' $0 $1 $2 etc

"$@"位置パラメータ"$1", "$2"などに展開されます。「$ 0」は含まれません。これは、位置パラメータではなくスクリプト名の特別なパラメータであるためです。これがzero、の代わりにダミー文字列(任意の文字列を使用可能)を追加する必要がある理由です$0。そうしないと、最初のファイルが失われます。

したがって、展開すると"$@"、次のようになります。

    bash -c '</dev/tty vim file1 file2' 

3. bash -cCOMMAND_STRINGを実行します。

    </dev/tty vim file1 file2 

</dev/tty対話モードで動作できるようにstdintoを設定します。/dev/ttyvim


+1これは、投票数が最も多い回答の複製のように見えますが、そうではありません。$0(ここでは「ゼロ」)プレースホルダが鍵となります。
追って通知があるまで一時停止します。

0

これらの答えはすべて欠けていることがわかりました。xargsの問題を乗り越えた後、私にとって最も簡単な方法は、汎用ボックスでこれらの検索とオープンを行うことです。

vim -O `grep -lir mySearchTerm *`

私が使用して何の問題を持っていないfindxargsしてgrep、私は構文が迷惑を見つけます。そしてvim、IDEとしてターミナルを使用し、常にプロパティのファイルを検索する毎日のコーダーとして、これが私が使用しているものです。

find . -path ./node_modules -prune -o -name '*.js' | xargs grep -i mySearchTermvimや他の方法でファイルを開くことと組み合わせる時間と場所があります。私にとって、それはめったにありません。

これが誰かを助けることを願っています。


2
FWIWでは、従来のバックティック表記を使用せ$(...)ず、代わりに使用することをお勧めします。これは、スクリプトのように、コマンドラインで重要なようではありませんが、私はそれがあなたの答えであることの使用にまだ良いことだと思う:)(参照ここここ
statox
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.