我正在Ubuntu系统上工作,目前我正在做的是:

if ! which command > /dev/null; then
   echo -e "Command not found! Install? (y/n) \c"
   read
   if "$REPLY" = "y"; then
      sudo apt-get install command
   fi
fi

大多数人都会这么做吗?还是有更优雅的解决方案?


当前回答

Use:

apt-cache policy <package_name>

如果没有安装,它将显示:

Installed: none

否则它将显示:

Installed: version

其他回答

这个命令是最容易记住的:

dpkg --get-selections <package-name>

如果已经安装,它会打印:

<包名称>安装

否则它会打印

没有找到匹配<package-name>的包。

这是在Ubuntu 12.04.1 (Precise穿山甲)上测试的。

为了更明确一点,这里有一些Bash脚本,用于检查包并在需要时安装它。当然,您可以在发现包丢失时执行其他操作,例如简单地使用错误代码退出。

REQUIRED_PKG="some-package"
PKG_OK=$(dpkg-query -W --showformat='${Status}\n' $REQUIRED_PKG|grep "install ok installed")
echo Checking for $REQUIRED_PKG: $PKG_OK
if [ "" = "$PKG_OK" ]; then
  echo "No $REQUIRED_PKG. Setting up $REQUIRED_PKG."
  sudo apt-get --yes install $REQUIRED_PKG
fi

如果脚本在GUI中运行(例如,它是一个Nautilus脚本),您可能想要用'gksudo'调用替换'sudo'调用。

我使用这个解决方案,因为我发现它是最直接的。

function must_install(){
   return "$(apt -qq list $var --installed 2> /dev/null |wc -l)"
}

function install_if() {
    unset install
    for var in "$@"
    do
        if $(must_install $var)
        then
            install+="${var} "
        fi
    done
    if [ -n "$install" ];
    then
        sudo apt-get install -qy $install
    fi
}

整洁的事情是,must_install返回1或0,然后通过调用if将其解释为true或false,因此我们不需要使用[]进行任何测试。

Install_if接受按空格分隔的任意数量的包。

问题是apt并不打算在脚本中使用,因此这可能在任何时候停止工作。8)

这个特性已经存在于Ubuntu和Debian的command-not-found包中。

我根据Nultyi的回答选择了一个:

MISSING=$(dpkg --get-selections $PACKAGES 2>&1 | grep -v 'install$' | awk '{ print $6 }')
# Optional check here to skip bothering with apt-get if $MISSING is empty
sudo apt-get install $MISSING

基本上,来自dpkg——get-selections的错误消息比其他大多数错误消息更容易解析,因为它不包括“deinstall”这样的状态。它还可以同时检查多个包,这是仅使用错误代码无法做到的。

解释/例子:

$ dpkg --get-selections  python3-venv python3-dev screen build-essential jq
dpkg: no packages found matching python3-venv
dpkg: no packages found matching python3-dev
screen                                          install
build-essential                                 install
dpkg: no packages found matching jq

因此grep从列表中删除已安装的包,awk从错误消息中提取包名,导致MISSING='python3-venv python3-dev jq',它可以简单地插入到安装命令中。

我不是盲目地发布apt-get install $PACKAGES,因为正如评论中提到的,这可能会意外地升级你没有计划的包;对于期望稳定的自动化流程来说,这并不是一个好主意。