Twitterをボケーッと眺めていたところ、xargsで呼び出したコマンドにキー入力をしたいという内容があったので、どうやったらできるのか調べてみた。
通常、対象のプロセスで標準入力が開いてないとだいたいの(というか、普通の)コマンドは処理を待たずに終了してしまう。なので、なんとかしてターミナルを標準入力として渡してやればいいということになる。
1. /dev/ttyを読み込ませる
以下のように、/dev/tty
をxargsで呼び出したコマンド内部で読み込ませる事で、ターミナルの入力を渡すことができる。
command... | xargs -I@ sh -c '</dev/tty command... @'
例えば、以下のようにすることでxargsで受け付けたファイルに対して対話式にrmをすることができる。
ls -1 | xargs -I @ sh -c '</dev/tty rm -i @'
2. xargsの-aオプションを使用する
この話題を会話していたツイートで、xargsの-aオプション(ファイルからxargsで処理するデータを受け付けるオプション)を利用する方法もあるよという内容をおしえてもらった。
失礼。xargsには-aで標準入力以外を受けられますので、/dev/tty 使わなくても行けるかと。
その場合、プロセス置換が簡明です。
つまり cmd | xargs の代わりに xargs -a ( cmd )
ただ、リダイレクトを駆使してもいけます。
参考: https://t.co/5FcKlrSLYO— angel as ㌵㌤の猫 (@angel_p_57) November 14, 2019
つまり、パイプから受け付けると標準入力がそのまま使えないので、-aでファイルとしてプロセス置換を利用してコマンドの結果を取得して、それをxargsからコマンドに渡すことで標準入力をそのまま使えるよ、という仕組みになる。 以下のような感じでコマンドを実行することになる。
xargs -I@ -a <(command...) command_in_xargs... @
rmでやった場合はこんな感じになるようだ。 command...にxargsに渡す出力を渡すコマンドが入る。
xargs -I@ -a <(command...) rm -i @
rmとかの単純なものであれば、xargs側で-pオプション(--interactive)を使って実行可否を確認するとかすればいいのだろうけど、コマンド個別の内容に回答するのならばこの方法が便利な気がする。
参考
- command line - xargs and vi - "Input is not from a terminal" - Unix & Linux Stack Exchange
- 8rivsn - Online Bash Interpreter & Debugging Tool - Ideone.com