如果未安装另一个程序,则运行该程序的最佳且最短的方法

如果未安装另一个程序,则运行该程序的最佳且最短的方法

我有这个代码:

#!/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,hashcommand如果需要的话。

这是一个紧凑的代码挑战,所以我想制作一个单行代码,使其简短,并尝试不重复变量名称或任何命令(除了||&&等等)

答案1

基于函数的方法可以产生最清晰的代码。至少有两种可能的变体,其中一种是 FloHimself 在上面的评论中建议的(这不是我喜欢的方式):

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设置为figlet实用程序的路径(如果存在),或者设置为banner其他路径,或者设置为echo(内置)(如果两者都不figlet存在banner)。

$cmd您可以定义一个命令来代替变量 ( ):

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

尽管在这里您最终会得到独立的echo实用程序而不是内置实用程序。另请注意,该散列命令会在hash -raka上消失rehash

相关内容