Bashスクリプトからのstdoutとstderrのリダイレクト

Bashスクリプトからのstdoutとstderrのリダイレクト

次のスクリプトがあります(行番号は参照にのみ使用されます)。

#!/bin/bash

1-  for version in `ls -al ./atk/ | grep ^d | grep -Ev '\.$' | awk -F' ' '{print $8}'`
2-      do
3-          grep $version ./atk/versions #&>/dev/null <--(first ran with this comment out)
4-          if [ $? -ne 0 ]
5-              then
6-                  printf '%-15s\n' "$version"
7-          fi
8-      done

現状のまま実行すると、ライン1は次を画面に送信します。 (私はこれを本当に望んでおらず、stdout / stderrがに移動したいの/dev/nullですが、これについては後で詳しく説明します。)

aaaaa--------
bbbbb       |
ccccc       |
ddddd       |------------ wil be stored in the version variable
eeeee       |
fffff       |
ggggg--------

$version行2では、以下を含む「バージョン」ファイルを探します。

12345
aaaaa
67890
ccccc
09876
fffff

$version「versions」ファイルにない場合、$ versionsは標準出力として印刷されます。

出力は次のようになります。

bbbbb
ddddd
eeeee
ggggg

ライン1が出力をに送り/dev/null、ライン3に出力をstdoutとstderrに送り返すにはどうすればよいですか?

奇妙なことは、3行目のコメントを削除すると/dev/nullstdoutとstderrが!にリダイレクトされますが、すべてがうまく機能することです。

私は以下を試しました:

for version in `ls -al ./atk/ | grep ^d &>/dev/null | grep -Ev '\.$' | awk -F' ' '{print $8}'` &>/dev/null

これは私が見たくないライン1の出力を抑制するだけでなく、コードを修正した後も見たいライン3の出力も抑制します。

for version in `ls -al ./atk/ | grep ^d | grep -Ev '\.$' | awk -F' ' '{print $8}'` &>/dev/null
    do
        exec &>/dev/tty  ++++++++++++++ trying to reset stdout and stderr back to the origal setting
        grep $version ./atk/versions #&>/dev/null

繰り返しますが、すべての出力をに送信するように明示的に要求すると、コメントアウトされていない3行が機能するのはなぜですか/dev/null

答え1

行1では、バックティック内のコマンドはそのコマンドを送信します。標準出力ループfor...。コマンドでエラーが発生しない限り(lsディレクトリパスの欠落に関する苦情の表示など)、画面に何も書きません。

3行目grepは書き込みます。標準出力、しかし。たぶん-q自動モードフラグが欲しいかもしれません。

私はそれがおそらくより簡単に処理できると思うので、実際にやりたいことが何であるかを理解しようとしています。

for item in atk/*
do
    test -d "$item" && echo "${item/*\/}" | grep -Fvf atk/versions
done

しかし、コマンド補間に逆引用符を使用することは、もはや良いコーディングスタイルとは見なされません。この構造を使用する方が良いです$( ... )。例えばfor version in $( ls ... awk )

関連情報