web-dev-qa-db-ja.com

シェルに与えられた各コマンドをパイプするにはどうすればよいですか?

.bashrcを編集して、シェルで実行されるすべてのコマンドが何かにパイプされるようにします。たとえば、

 $ Sudo apt update
  _________________
< Sudo apt update >
 -----------------
    \   ^__^
     \  (oo)\_______
        (__)\       )\/\
            ||----w |
            ||     ||

私はかなり似たものを管理しましたが、完全ではありません:

$ bash
$ exec > >(cowsay)
$ echo "Hello AU!"
$ exit
 _______
< Hello AU! >
 -------
    \   ^__^
     \  (oo)\_______
        (__)\       )\/\
            ||----w |
            ||     ||

現在のシェルを終了した後にのみ発生するため、望ましい結果ではありません。

主に楽しみ/学習目的のためです。

13
M. Becerra

メソッドを少し変更することができます。 cowsayに直接パイピングする代わりに、区切り文字まで出力を読み取り、その出力をcowsayに送信し、コマンドごとにその文字を出力します。

exec > >(while IFS= read -d '' -r line; do if [[ -n $line ]]; then echo; printf "%s\n" "$line" | cowsay; fi; done)
Prompt_COMMAND='printf "\0"'

ここでは、ASCII NUL文字を使用しています。コマンド出力に表示されそうにないものを使用できます。

これはプロンプトの後に印刷されるため、出力は見苦しくなります。

$ export LC_ALL=C
$ exec > >(while IFS= read -d '' -r line; do if [[ -n $line ]]; then echo; printf "%s\n" "$line" | cowsay; fi; done)
$ Prompt_COMMAND='printf "\0"'
$ ls
$
 ______________________________________
/ Desktop Documents Downloads Music    \
| Pictures Public Templates Videos
\ examples.desktop                     /
 --------------------------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

$ echo foo
$
 ______
< foo  >
 ------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

これにより、複雑な出力を試みるコマンドやテキストユーザーインターフェイスを持つコマンド(コマンドラインエディター、ポケットベルなど)が破損することに注意してください。

exec > >(...)が何をするかを既に知っていると仮定すると、プロセス置換の部分は次のとおりです。

  • while IFS= read -d '' -r line; do ... done:これは、ASCII NUL文字で区切られたデータを読み取るためのかなり一般的なイディオムです。

    • IFS=はIFSを空の文字列に設定し、フィールド分割を無効にします
    • -rは、readが入力内の\を特別に処理しないようにします(たとえば、\n\nとして読み取られ、改行文字に変換されません)。
    • -d ''は、readにNUL文字まで読み込むように指示する方法です

    そのため、入力の内容を可能な限り保持しながら、全体がNUL区切りセクションの入力をループします。

  • if [[ -n $line ]]; then ... fi; done-これまでに読み込まれた入力が空でない場合にのみ機能します。
  • echo; printf "%s\n" "$line" | cowsay;-カウセイの出力がプロンプトと衝突しないように、先頭の空行を出力し、それまでに読み取った入力をカウセイに送信します。 printfは、echoよりも信頼性が高く安全です。
12
muru

trapおよびbashのDEBUGシグナルを悪用できます。

trap 'bash -c "$BASH_COMMAND" | cowsay' DEBUG

実行例

$ trap 'bash -c "$BASH_COMMAND" | cowsay' DEBUG
$ echo "AU is awesome!"
 __________________
< AU is awesome! >
 ------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
AU is awesome!

ただし、これにより、後でコマンドが実行されます。 ilkkach のおかげで、それを回避する方法を見つけました。

$ shopt -s extdebug
$ trap 'bash -c "$BASH_COMMAND" | cowsay; false' DEBUG
$ echo "AU is awesome!"
 __________________
< AU is awesome! >
 ------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
16
dessert