次のようにvim
からfind | xargs
を呼び出す場合:
find . -name "*.txt" | xargs vim
あなたはについての警告を受け取ります
Input is not from a terminal
あとはかなり動作がおかしい端末。 なぜそれは何ですか?
この質問は、明示的にwhyについてであり、回避方法についてではありませんでした。これは尋ねられ、答えられた 他の場所 。
xargs
を介してプログラムを呼び出すと、プログラムのstdin(標準入力)は_/dev/null
_を指します。 (xargsはoriginal stdinを知らないため、次善の策です)
$ true | xargs filan -s 0 chrdev /dev/null 1 tty /dev/pts/1 2 tty/dev/pts/1 $ true | xargs ls -l /dev/fd/
Vimはそのstdinが制御端末と同じであることを期待し、さまざまな端末関連のioctlをstdinで直接実行します。 _/dev/null
_(またはtty以外のファイル記述子)で実行すると、それらのioctlは無意味になり、ENOTTYを返しますが、これは黙って無視されます。
より具体的な原因についての私の推測:起動時にVimは古い端末設定を読み取って記憶し、終了時にそれらを復元します。私たちの状況では、tty以外のfd(ファイル記述子)に対して「古い設定」が要求されると、Vimはすべての値を空にしてすべてのオプションを無効にし、不用意に端末に設定します。
これは、_vim < /dev/null
_を実行して終了し、次にstty
を実行することで確認できます。これにより、_<undef>
_ sが大量に出力されます。 Linuxで_stty sane
_を実行すると、端末が再び使用可能になります(ただし、willは_iutf8
_などのオプションを失い、後で軽度の不快感を引き起こす可能性があります) 。
can端末制御用に_/dev/tty
_を開くため、これはVimのバグと考えることができますが、そうではありません。 (起動時のある時点で、Vimはstderrをstdinに複製します。これにより、書き込み用に開かれたfdから入力コマンドを読み取ることができますが、それでも十分に早くは行われません。)
(大雑把な説明に続き、xargs
はstdin
を/dev/null
に向けます。)
この問題のソリューションは、-o
パラメータをxargs
に追加することです。 man xargs
から:
-o
コマンドを実行する前に、子プロセスで
/dev/tty
としてstdinを再度開きます。これは、xargs
でインタラクティブアプリケーションを実行する場合に便利です。
したがって、次のコード行が機能するはずです。
見つける。 -name "* .txt" | xargs -o vim
GNU xargsは、2017年のリリース以降、この拡張機能をサポートしています(長いオプション名--open-tty
を使用)。
Xargsの古いバージョンまたは他のバージョンの場合、/dev/tty
を明示的に渡して問題を解決できます。
find . -name "*.txt" | xargs bash -c '</dev/tty vim "$@"' ignoreme
(ignoreme
は$ 0を占めるために存在するため、$ @はすべてxargsからの引数です。)
最も簡単な方法:
vim $(find . -name "*foo*")
Xargsにパイプするのではなく、findで-execオプションを使用すると、問題なく動作します。
find . -type f -name filename.txt -exec vi {} +
代わりにGNU Parallelを使用してください:
find . -name "*.txt" | parallel -j1 --tty vim
または、すべてのファイルを一度に開きたい場合:
find . -name "*.txt" | parallel -Xj1 --tty vim
次のようなファイル名も正しく処理します。
My brother's 12" records.txt
詳細については、紹介動画をご覧ください: http://www.youtube.com/watch?v=OpaiGYxkSuQ
多分最高ではないかもしれませんが、ここで私が使用するスクリプト(名前はvim-open
)です。
#!/usr/bin/env Ruby
require 'shellwords'
inputs = (ARGV + (STDIN.tty? ? [] : STDIN.to_a)).map(&:strip)
exec("</dev/tty vim #{inputs.flatten.shelljoin}")
たとえば、vim-open a b c
およびls | vim-open
で動作します