我正在开发一个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
大多数人会这样做吗?还是有更优雅的解决方案?
答案 0 :(得分:295)
要检查是否安装了packagename
,请输入:
dpkg -s <packagename>
您也可以使用具有整洁输出的dpkg-query
,并接受外卡。
dpkg-query -l <packagename>
要查找包含command
的软件包,请尝试:
dpkg -S `which <command>`
有关详细信息,请参阅文章 Find out if package is installed in Linux 和dpkg cheat sheet。
答案 1 :(得分:73)
为了更加明确一点,这里有一些bash脚本可以检查包并在需要时安装它。当然,您可以在发现缺少包时做其他事情,例如只需退出错误代码。
PKG_OK=$(dpkg-query -W --showformat='${Status}\n' the.package.name|grep "install ok installed")
echo Checking for somelib: $PKG_OK
if [ "" == "$PKG_OK" ]; then
echo "No somelib. Setting up somelib."
sudo apt-get --force-yes --yes install the.package.name
fi
如果脚本在GUI中运行(例如,它是Nautilus脚本),您可能希望将'sudo'调用替换为'gksudo'调用。
答案 2 :(得分:66)
这个单线为'nano'包返回1(已安装)或0(未安装)..
$(dpkg-query -W -f='${Status}' nano 2>/dev/null | grep -c "ok installed")
即使包不存在/也不可用。
如果未安装'nano'软件包,则以下示例将安装'nano'软件包。
if [ $(dpkg-query -W -f='${Status}' nano 2>/dev/null | grep -c "ok installed") -eq 0 ];
then
apt-get install nano;
fi
答案 3 :(得分:11)
我提供此更新,因为Ubuntu在回答此问题时添加了“个人包存档”(PPA),并且PPA包具有不同的结果。
未安装Native Debian存储库软件包:
~$ dpkg-query -l apache-perl
~$ echo $?
1
在主机上注册并安装的PPA包:
~$ dpkg-query -l libreoffice
~$ echo $?
0
在主机上注册但未安装的PPA包:
~$ dpkg-query -l domy-ce
~$ echo $?
0
~$ sudo apt-get remove domy-ce
[sudo] password for user:
Reading package lists... Done
Building dependency tree
Reading state information... Done
Package domy-ce is not installed, so not removed
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
同时发布于:https://superuser.com/questions/427318/test-if-a-package-is-installed-in-apt/427898
答案 4 :(得分:6)
这看起来效果很好。
$ sudo dpkg-query -l | grep <some_package_name> | wc -l
0
,如果已安装则返回> 0
。答案 5 :(得分:6)
UpAndAdam写道:
但是,您不能仅仅依靠这里的返回代码来编写脚本
在我的体验中,您可以依赖于dkpg的退出代码。
dpkg -s 的返回代码 0 如果已安装软件包, 1 (如果不是),那么我找到的最简单的解决方案是:
dpkg -s <pkg-name> 2>/dev/null >/dev/null || sudo apt-get -y install <pkg-name>
对我来说很好......
答案 6 :(得分:6)
dpkg -s
编程用法
我喜欢dpkg -s
,因为如果没有安装任何软件包,它会以状态1
退出,从而很容易实现自动化:
pkgs='qemu-user pandoc'
if ! dpkg -s $pkgs >/dev/null 2>&1; then
sudo apt-get install $pkgs
fi
另请参阅:
在Ubuntu 18.10上测试。
答案 7 :(得分:3)
灵感来自上面的克里斯
#! /bin/bash
installed() {
return $(dpkg-query -W -f '${Status}\n' "${1}" 2>&1|awk '/ok installed/{print 0;exit}{print 1}')
}
pkgs=(libgl1-mesa-dev xorg-dev vulkan-tools libvulkan-dev vulkan-validationlayers-dev spirv-tools)
missing_pkgs=""
for pkg in ${pkgs[@]}; do
if ! $(installed $pkg) ; then
missing_pkgs+=" $pkg"
fi
done
if [ ! -z "$missing_pkgs" ]; then
cmd="sudo apt install -y $missing_pkgs"
echo $cmd
fi
答案 8 :(得分:3)
我发现上面的所有解决方案都会产生误报,如果安装了一个软件包然后将其删除,那么安装软件包仍保留在系统上。
要复制:
安装包apt-get install curl
删除包apt-get remove curl
现在测试以上答案。
以下命令似乎解决了这个问题:
dpkg-query -W -f='${Status}\n' curl | head -n1 | awk '{print $3;}' | grep -q '^installed$'
这将产生明确的结果 已安装或未安装
答案 9 :(得分:3)
我已根据Nultyi's answer确定了一个:
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
因为正如评论中所提到的,这可能意外地升级你没有计划的包裹;对于预期稳定的自动化流程来说,这并不是一个好主意。
答案 10 :(得分:2)
$name="rsync"
[ `which $name` ] $$ echo "$name : installed" || sudo apt-get install -y $name
答案 11 :(得分:2)
这样做。 apt-get install
是幂等的。
sudo apt-get install command
答案 12 :(得分:2)
使用:
apt-cache policy <package_name>
如果未安装,则会显示:
Installed: none
否则会显示:
Installed: version
答案 13 :(得分:1)
此功能已存在于Ubuntu和Debian的 command-not-found
包中。
答案 14 :(得分:1)
在本地而不是在docker中运行测试时,我有类似的要求。基本上,我只想安装找到的所有.deb文件(如果尚未安装)。
this.setState({ emails: this.state.emails.slice(0, -1) });
我想他们唯一能看到的问题是它不检查软件包的版本号,因此如果.deb文件是较新的版本,则不会覆盖当前安装的软件包。
答案 15 :(得分:1)
对于Ubuntu,apt提供了一种相当不错的方法来实现这一点。以下是Google Chrome的示例:
apt -qq list google-chrome-stable 2>/dev/null | grep -qE "(installed|upgradeable)" || apt-get install google-chrome-stable
我将错误输出重定向到null,因为apt警告不要使用它的&#34;不稳定的cli&#34;。我怀疑列表包是稳定的所以我认为可以抛弃这个警告。 -qq使得超级安静。
答案 16 :(得分:1)
apt list [packagename]
似乎是在dpkg和更旧的apt- *工具之外进行此操作的最简单方法
答案 17 :(得分:0)
已经讲了很多事情,但对我来说,最简单的方法是:
dpkg -l | grep packagename
答案 18 :(得分:0)
在Bash中:
let isEqual = true;
function deepEqual(object1, object2) {
if (!((typeof(object1) == 'object' && typeof(object2) == 'object') || (object1 && object2))) {
return isEqual = object1 === object2;
} else if (typeof(object1) == 'object' && typeof(object2) == 'object') {
if ((object1 && object2)) {
let object1Keys = Object.keys(object1);
let object2Keys = Object.keys(object2);
if (object1Keys.length == object2Keys.length) {
for (let index = 0; index < object1Keys.length; index++) {
if (isEqual) {
if (!(typeof(object1[object1Keys[index]]) == 'object' && typeof(object2[object2Keys[index]]) == 'object')) {
isEqual = (object1[object1Keys[index]] === object2[object2Keys[index]]) && (object1Keys[index] === object2Keys[index]);
} else {
deepEqual(object1[object1Keys[index]], object2[object2Keys[index]]);
}
} else {
return isEqual = false;
}
}
}
}
}
return isEqual;
}
let obj1 = {
a: 'somestring',
b: 42,
c: {
1: 'one',
2: {
4: 'Three'
}
}
};
let obj2 = {
a: 'somestring',
b: 42,
c: {
1: 'one',
2: {
3: 'Three'
}
}
};
console.log("obj1 == obj2 : ");
console.log(deepEqual(obj1, obj2));
let obj3 = {
a: 'somestring',
b: 42,
c: {
1: 'one',
2: {
3: 'Three'
}
}
};
let obj4 = {
a: 'somestring',
b: 42,
c: {
1: 'one',
2: {
3: 'Three'
}
}
};
console.log("obj3 == obj4 : ");
isEqual = true;
console.log(deepEqual(obj3, obj4));
let obj = {name: {gender: "F"}, age: 20};
isEqual = true;
console.log(deepEqual(obj, {name: {gender: "F"}, age: 20}));
请注意,您可以在PKG中使用包含多个软件包的字符串。
答案 19 :(得分:0)
which <command>
if [ $? == 1 ]; then
<pkg-manager> -y install <command>
fi
答案 20 :(得分:0)
我使用以下方式:
which mySQL 2>&1|tee 1> /dev/null
if [[ "$?" == 0 ]]; then
echo -e "\e[42m MySQL already installed. Moving on...\e[0m"
else
sudo apt-get install -y mysql-server
if [[ "$?" == 0 ]]; then
echo -e "\e[42mMy SQL installed\e[0m"
else
echo -e "\e[42Installation failed\e[0m"
fi
fi
答案 21 :(得分:0)
如今,apt-get
似乎有一个选项--no-upgrade
可以满足OP的要求:
--no-upgrade
不要升级软件包。与安装结合使用时,如果已经安装了列出的软件包,则不进行升级将阻止对其进行升级。
https://linux.die.net/man/8/apt-get的帮助页
因此您可以使用
apt-get install --no-upgrade package
和package
仅在未安装时安装。
答案 22 :(得分:0)
如果已安装,则显式打印0,否则仅使用awk打印1:
dpkg-query -W -f '${Status}\n' 'PKG' 2>&1|awk '/ok installed/{print 0;exit}{print 1}'
,或者如果您喜欢以其他方式选择安装1则安装0,否则:
dpkg-query -W -f '${Status}\n' 'PKG' 2>&1|awk '/ok installed/{print 1;exit}{print 0}'
**用您的包裹名称替换PKG
便捷功能:
installed() {
return $(dpkg-query -W -f '${Status}\n' "${1}" 2>&1|awk '/ok installed/{print 0;exit}{print 1}')
}
# usage:
installed gcc && echo Yes || echo No
#or
if installed gcc; then
echo yes
else
echo no
fi
答案 23 :(得分:0)
这个命令是最令人难忘的:
dpkg --get-selections <package-name>
如果已安装,则打印:
&LT;包名称&gt;安装
否则打印
找不到与&lt; package-name&gt;匹配的包。
这是在Ubuntu 12.04.1(精确穿山甲)上测试的。
答案 24 :(得分:0)
我使用这个解决方案,因为我觉得它最直接。
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,因此我们不需要任何 test
使用 []
.
install_if
接受由空格分隔的任意数量的包。
问题是,apt
不打算在脚本中使用,因此这可能随时停止工作。 8)