他のプログラムがインストールされていない場合に実行する最良かつ最短の方法

他のプログラムがインストールされていない場合に実行する最良かつ最短の方法

私はこのコードを持っています:

#!/bin/bash

num=${1:-undefined}
cmd=$(which {banner,echo} | head -n1)

until [[ "$num" =~ ^[0-9]+$ ]]; do 
    read -p "Type a number: " num
done

for ((num;num>=0;num--)); do
   $cmd $num
   sleep 1
done

しかし、プログラムがインストールされているかどうかを知るより良い方法があると思います。私はこれを試しました。しかし、私はそれが明確ではないと思います。

  1. which banner && cmd=banner || cmd=echo
  2. cmd=$(eval 'which '{banner,echo}'||' :)
  3. cmd=$(which {banner,echo} | head -n1)
  4. cmd=$(which banner || which echo)

私は他のものよりも3を好むが、誰かがこれを行うための良い方法を見つけるのを助けることができると思いました。typeまたは必要に応じてhash使用を受け入れます。command

これは簡潔なコードチャレンジなので、一行にして短く保ち、変数名やコマンド(||&&などは除く)を繰り返さないようにしました。

答え1

関数ベースのアプローチは、最も明確なコードを生成します。少なくとも2つのバリエーションがあり、そのうちの1つはFloHimが上記のコメントで提案したものです(これは私の好きな方法ではありません)。

function myprint
{
    if type banner >/dev/null
    then  banner "$@"
    else  echo "$@"
    fi
}

myprint "Hello World!"

または - 私が好むバリアント - 使用条件付き関数の定義:

if type banner >/dev/null
then  function myprint { banner "$@" ;}
else  function myprint { echo "$@" ;}
fi

myprint "Hello World!"

if呼び出しごとの条件付きオーバーヘッドがなく、文字列や変数式を繰り返す必要はありません(他の提案のように)。

答え2

最も簡単な方法は走ることです

command1 "hello world" || command2 "hello world"

最初のコマンドがないと、左側のコマンドが||失敗するため、右側のコマンドが実行されます。なぜ最初にテストする必要があるのか​​理解できません。やってみて、失敗したら別のことをしてください。

不足しているコマンドによるエラーメッセージを無視して重複文字列を避けると、状況が少し良くなる可能性があります。

string="Hello world!"
banner "$string" || echo "$string"

コマンドが存在することを本当に確認する必要がある場合は、次のようにします。

command="banner"
type "$command"  2>/dev/null || command="echo"
"$command" "Hello world!"

答え3

zshコマンドをそのパスにマップする特別な連想配列で、$commands次のことができます。

cmd=${commands[figlet]-${commands[banner]-echo}}

ユーティリティパスがある場合はそのパスに設定し、別のパスに設定し、両方がない場合(組み込み)に$cmd設定します。figletbannerechofigletbanner

$cmd変数()の代わりにコマンドを定義できます。

hash cmd=${commands[figlet]-${commands[banner]-$commands[echo]}}

echoここでは、組み込みユーティリティではなくスタンドアロンユーティリティで終わります。また、hash -rakaではhashコマンドが消えますrehash

関連情報