こんにちは。駅奪取チームエンジニアのid:dorapon2000です。
よくシェルスクリプトのIF文に >/dev/null 2>&1
を書いて条件文とすることはありませんか。実行結果の成否をIF条件として利用したいのであって実際に出力したいわけではないケースです。
実は身近なコマンドでもオプションで出力を抑制できます。3つ紹介します。
検証環境
- Ubuntu 16.04
- bash 4.3.48
grep --quiet
特定の文字列を含むときにだけif文を実行します。
まず、>/dev/null 2>&1
を使う書き方。grepに引っかかると0を返し(True)、grepに引っかからないと1を返します(False)。
if cat /var/log/syslog | grep "Error" >/dev/null 2>&1; then echo 'Found' fi
--quiet
オプションを使うことで、出力を抑制してくれます。
if cat /var/log/syslog | grep --quiet "Error"; then echo 'Found' fi # -q でも可 if cat /var/log/syslog | grep -q "Error"; then echo 'Found' fi
以下のサイトでは、--quiet
を使うことで高速化もするという嬉しい情報もあります。
シェルスクリプトでファイルに特定の文字が含まれているかどうかを高速に判定する方法 | ゲンゾウ用ポストイット
git diff --quiet
git差分があるときにだけif文を実行します。
まず、>/dev/null 2>&1
を使う書き方。git diff
は差分のありなしに関わらず正常終了の0を返すため、ifで使うには --exit-code
オプションが必要です。差分があるときに1を(False)、差分がないときに0を返すようになります(True)
# ① --exit-code を使う場合 if ! git diff --exit-code >/dev/null 2>&1; then echo 'Diff' fi
あるいは --exit-code
を使わず以下のように書く人もいるでしょう。
# ② [を使う if [ `git diff | wc -l` -gt 0 ]; then echo 'Diff' fi # ③ bash構文を使う if [[ `git diff | wc -l` > 0 ]]; then echo 'Diff' fi
さて、git diffにも --quiet
オプションがあります。さらに --quiet
オプションは暗黙的に --exit-code
オプションを利用しており、一石二鳥です。
if ! git diff --quiet; then echo 'Diff'; fi
非常にスッキリしましたね!
apt list -qq
aptで特定のパッケージをインストールしていなかったらインストールしたいことは多いです。
まずは、前述した grep --quiet
を使うやり方から。
if apt list --installed sl | grep -q sl ; then sudo apt install sl -y fi
これでいいじゃん!ですが、aptの -qq
オプションでも同じことができるため紹介します。
aptの -qq
オプションは --quiet
オプションをより強力にしたもので、進捗情報を消してくれます。ログ出力のためにあるオプションのようです。完全に出力を消すものではありません。
$ apt list --installed sl 一覧表示... 完了 # <-- これが消える sl/xenial,now 3.03-17build1 amd64 [インストール済み] $ apt list -qq --installed sl sl/xenial,now 3.03-17build1 amd64 [インストール済み]
したがって、最初のif文は以下のように書き換える事ができます。grep ^
でパイプで渡される出力が空かどうかを判定します。
if ! apt list -qq --installed sl | grep -q ^; then sudo apt install sl -y fi
aptの警告について
上記例を実行すると警告が表示されます。
WARNING: apt does not have a stable CLI interface. Use with caution in scripts.
書かれているとおりで、aptは出力フォーマットが安定しているわけではないため、出力結果を加工するスクリプトはあまりよろしくないようです。
可能なら別のコマンドを利用したほうがよく、apt list --installed
に関しては dpkg -l
で代替できます。
if ! dpkg -l | grep -q sl; then sudo apt install sl -y fi