Reliably check if a package is installed or not
I have a simple requirement. I want to define several variables that will correspond to any number of given packages I want to install via a shell script. Sample code below:
MISC="shutter pidgin" WEB="apache2 mongodb" for pkg in $MISC $WEB; do if [ "dpkg-query -W $pkg | awk = """ ]; then echo -e "$pkg is already installed" else apt-get -qq install $pkg echo "Successfully installed $pkg" fi done
Everything kinda works, but the logic seems flawed because it’s not reliably installing the packages I want. It either says they’ve been installed already or it’s trying to install packages that have already been installed previously. I’ve also been trying with command -v or the following:
if [ "dpkg -l | awk | grep --regexp=^$pkg$ != """ ]; then
And even with the -n and -z flags to check if the returned string was empty. Pretty sure I’m missing some good sense here. Do you have any idea what I could do to make sure a package is actually installed or not? Thanks!
What harm there is, if you call apt-get install for installed packages, too? You could just call apt-get install $MISC $WEB .
4 Answers 4
Essentially you only need to replace the if condition with
if dpkg --get-selections | grep -q "^$pkg[[:space:]]*install$" >/dev/null; then
It is not possible to use dpkg-query , because it returns true also for packages removed but not purged.
Also I suggest to check the exit code of apt-get before giving the successful message:
if apt-get -qq install $pkg; then echo "Successfully installed $pkg" else echo "Error installing $pkg" fi
@Taymon: redirect both stdin and stderr to the given file ( /dev/null in this case), because we don’t need the output, only the exit code. It only works in bash (the first line of the script has to be #!/bin/bash ) otherwise use >/dev/null 2>&1 .
Beware: if using bash and the pipefail option is set, then the grep -q can generate Heisenbugs. Basically, grep exits before dpkg finishes writing (you want a 0 exit status in that case) so dpkg fails writing to the pipe (which instead generates a non-0 exit status). Either make sure pipefail is not set, or abandon the (probably tiny) efficiency gains of the «-q» option.
This answer internally produces as many lines as there are packages known by the system (2870 on my machine), to be then filtered by grep (thus potentially slow), while @jarno’s answers uses dpkg-query that returns only one line (potentially faster). On a Raspberry Pi 3, the one based on dpkg-query appears (though inconsistently) faster.
You can test it by dpkg-query:
if dpkg-query -W -f'$' "$pkg" 2>/dev/null | grep -q "ok installed"; then
Note that * and ? are wildcards, if they appear in $pkg. I guess dpkg-query may print «reinst-required installed» instead of «ok installed», if package is broken and needs to be reinstalled by command apt-get install —reinstall which can be used to install new packages as well.
#to check package is installed or not without distribution dependency #!/bin/bash read -p "Package Name: " pkg which $pkg > /dev/null 2>&1 if [ $? == 0 ] then echo "$pkg is already installed. " else read -p "$pkg is not installed. Answer yes/no if want installation_ " request if [ $request == "yes" ] then yum install $pkg fi fi
This seems similar to what OP wanted to do so I thought I’d share:
function package_check() < # Tell apt-get we're never going to be able to give manual feedback: export DEBIAN_FRONTEND=noninteractive sudo apt-get update #PKG_LIST='build-essential devscripts debhelper' #if input is a file, convert it to a string like: #PKG_LIST=$(cat ./packages.txt) PKG_LIST=$1 for package in $PKG_LIST; do CHECK_PACKAGE=$(sudo dpkg -l \ | grep --max-count 1 "$package" \ | awk '') if [[ ! -z "$CHECK_PACKAGE" ]]; then echo "$package" 'IS installed'; pkg_installed="yes" else echo "$package" 'IS NOT installed, installing'; sudo apt-get --yes install --no-install-recommends "$package" pkg_installed="no" package_install "$package" fi done # Delete cached files we don't need anymore sudo apt-get clean >
$ source ./package_check.bash $ PACKAGES=$(cat ./packages.txt) && package_check "$PACKAGES" Hit:1 http://deb.debian.org/debian bullseye-updates InRelease Hit:2 http://security.debian.org/debian-security bullseye-security InRelease Hit:3 http://deb.debian.org/debian bullseye InRelease Hit:4 http://mirrors.rit.edu/mxlinux/mx-packages/mx/repo bullseye InRelease Reading package lists. Done build-essential IS installed devscripts IS installed debhelper IS installed 2048 IS NOT installed, installing Reading package lists. Done Building dependency tree. Done Reading state information. Done The following NEW packages will be installed: 2048
How can I find out if a specific program is installed? [duplicate]
I want to find out if a program — Chromium for example — is installed on Ubuntu or not. Manually or as a package. How do I know if a program is installed via command line?
5 Answers 5
And there’s always apt-cache policy (no sudo needed).
oli@bert:/$ apt-cache policy gnuift gnuift: Installed: (none) Candidate: 0.1.14-11 Version table: 0.1.14-11 0 500 http://archive.ubuntu.com/ubuntu/ oneiric/universe amd64 Packages
oli@bert:/$ apt-cache policy firefox firefox: Installed: 8.0+build1-0ubuntu0.11.10.3 Candidate: 8.0+build1-0ubuntu0.11.10.3 Version table: *** 8.0+build1-0ubuntu0.11.10.3 0 500 http://archive.ubuntu.com/ubuntu/ oneiric-updates/main amd64 Packages 500 http://archive.ubuntu.com/ubuntu/ oneiric-security/main amd64 Packages 100 /var/lib/dpkg/status 7.0.1+build1+nobinonly-0ubuntu2 0 500 http://archive.ubuntu.com/ubuntu/ oneiric/main amd64 Packages
Or dpkg : dpkg -l | grep -E ‘^ii’ | grep . When it’s not installed it won’t show output. When it is, it’ll show something like:
oli@bert:~$ dpkg -l | grep -E '^ii' | grep firefox ii firefox 8.0+build1-0ubuntu0.11.10.3 Safe and easy web browser from Mozilla ii firefox-branding 8.0+build1-0ubuntu0.11.10.3 Safe and easy web browser from Mozilla - transitional package ii firefox-globalmenu 8.0+build1-0ubuntu0.11.10.3 Unity appmenu integration for Firefox ii firefox-gnome-support 8.0+build1-0ubuntu0.11.10.3 Safe and easy web browser from Mozilla - GNOME support ii firefox-locale-en 8.0+build1-0ubuntu0.11.10.3 English language pack for Firefox
It’s obviously a fuzzier search but handy if you’re not sure which package you’re looking for.
For manually installed things.
A bit harder but if they’re on the current path, you could just run them. That’s a bit of mission so I’d rather just run:
oli@bert:/$ which chromium-browser /usr/bin/chromium-browser
oli@bert:/$ which gnuift # returns nothing
Which is better?
That depends on the sanity of user. There’s nothing to stop somebody installing something called chromium-browser that isn’t Chromium. They could even package it up incorrectly and install that. Neither method can be 100% certain.
But assuming the owner is sane — packages should be good enough for most people.
e,g, Chromium, Run in terminal chromium-browser if it’s install, it will be open. If it’s not you will get
chromium-browser: command not found
To check whether a package is install also
dpkg -l | grep chromium-browser
You will get like this if it is installed:
To listing all installed packages, just use
Use Ubuntu Software Center type chromium
If you see the green icon like this:
That means it is installed 🙂
nice answer helpful. but here when i hit dpkg -l to check all package installed, it listed all but i was unable to see list till 1st program. Do you knw how can i see it till 1st program
For a graphical view, open the Software Centre , and click on the Installed button at the top:
You may want to click the Show X technical items button if you’re interested in system stuff, but Chromium would be there on the list anyway.
If you want a command line solution, then dpkg is your friend:
$ dpkg -l Desired=Unknown/Install/Remove/Purge/Hold | Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend |/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad) ||/ Name Version Description +++-==============-==============-============================================ ii accountsservic 0.6.14-1git1ub query and manipulate user account informatio ii acl 2.2.51-3 Access control list utilities ii acpi-support 0.138 scripts for handling many ACPI events ii acpid 1:2.0.10-1ubun Advanced Configuration and Power Interface e ii acroread 9.4.6~enu-0one Adobe Reader ii acroread-commo 9.4.6~enu-0one Adobe Reader - Common Files ii adduser 3.112+nmu1ubun add and remove users and groups ii adium-theme-ub 0.3.1-0ubuntu1 Adium message style for Ubuntu ii aisleriot 1:3.2.1-0ubunt Solitaire card games ii alacarte 0.13.2-2ubuntu easy GNOME menu editing tool ii alsa-base 1.0.24+dfsg-0u ALSA driver configuration files ii alsa-utils 1.0.24.2-0ubun Utilities for configuring and using ALSA .
How to check if a package is installed from Bash?
I need to check if a specific package is installed on a machine from within a Bash script. I found something like that but I don’t know how use it correctly.
dpkg -l | grep "ansible" | awk '' if [$? -eq 0]; then echo OK else echo FAIL fi
I need check, if command dpkg -l | grep «ansible» | awk ‘
dpkg -l | grep "ansible" | awk ''
ansible = $? if [$? -eq 0]; then echo OK else echo FAIL fi
that’s not work, but I’m sure I doing that wrong. How can I read result from dpkg -l | grep «ansible» | awk ‘
What do you want to do by that code? Do you want to check if a package whose name contains ‘ansible’ is installed? All lines printed by dpkg -l do not indicate installed packages. There may be removed packages, too. Note also that dpkg -l list much more than just package names, so you have to be more careful, if you examine its output by grep .
3 Answers 3
You can check if the software is installed on this way:
if [ "$(dpkg -l | awk '/ansible/ '|wc -l)" -ge 1 ]; then echo OK else echo FAIL fi
You can’t use exit code because it will be from awk and in this case always be 0
Great! I have one more question. Can you tell me how should it look, if I need check software is installed in pip so command pip list. If I check dpkg -l for pip list I got that message in terminal DEPRECATION: The default format will switch to columns in the future. You can use —format=(legacy|columns) (or define a format=(legacy|columns) in your pip.conf under the [list] section) to disable this warning.
@BElluu, please use «Ask Question» button and create new question. But in general you can replace dpkg -l with pip list to use as source the list of packages, installed with pip
This is bad practice in several ways: there could be several packages whose name contain string «ansible», but it could be that none of them is named «ansible». The string could be something else in the output of dpkg -l than package name. Why use awk here, as the same could be done by grep ‘ansible’ that may give non-zero exit code? wc -l is not needed in checking if a string is not null in Bash. So I wonder why this is accepted answer. I have given another answer.
If you know the exact package name, you can just ask dpkg if it’s installed with
$ dpkg -l pulsea dpkg-query: no packages found matching pulsea
The exit code is also 1 (fail) if a package isn’t installed, you can test for that (as seen later).
$ dpkg -l pulseaudio Desired=Unknown/Install/Remove/Purge/Hold | Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend |/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad) ||/ Name Version Architecture Description +++-==================-==============-==============-========================= ii pulseaudio 10.0-1+deb9u1 i386 PulseAudio sound server
Here the exit code is 0 (success), so you can do this too
$ if dpkg -l pulseaudio; then echo yes;fi Desired=Unknown/Install/Remove/Purge/Hold | Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend |/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad) ||/ Name Version Architecture Description +++-==================-==============-==============-========================= ii pulseaudio 10.0-1+deb9u1 i386 PulseAudio sound server yes
Note the trailing «yes» above. But now since you can just use the exit code, you don’t really care about dpkg’s output, so ignore it with an if or an && (AND list):
$ if dpkg -l pulseaudio >/dev/null; then echo yes;fi yes $ dpkg -l pulseaudio >/dev/null && echo yes yes
dpkg can also match partial names, using asterisks, like
About pipes and their exit status, if you want to see if a command somewhere in a pipeline has failed you’ll have to do something like examining the $ :
And like $? , $ changes with every command, so if you want to examine them more than once you have to save them to another variable first. In your example
$? has already changed by the if test, and it’s probably 0 since assigning a variable like that almost always succeeds.