40

I want to write a bash script allowing me to check, whether a certain package is already installed in arch linux.

How can I do that?

Random Citizen
  • 1,272
  • 3
  • 14
  • 28

6 Answers6

59

You should use Pacman, the package manager of Arch Linux.

You want to use the -Q operation to query the installed local package database and the -i option to get information on the package.

This gives you

pacman -Qi <packageName>

You can then use the exit code to determine if the packages existes on the system or not (0 the package exists, 1 it doesn't)

The usage of -i rather than -s ensures you will check for exactly that package and not for the presence of a a package containing the package name in its name.

For example if I search for chromium (the web browser) on a system where only chromium-bsu (the game) is installed,

# This exits with 1 because chromium is not installed
pacman -Qi chromium 
# This exits with 0 because chromium-bsu is installed
pacman -Qs chromium

As Random Citizen pointed out, you certainly want to redirect any output to /dev/null if you are writing a script and don't want Pacman to pollute your output:

pacman -Qi <packageName> > /dev/null
Community
  • 1
  • 1
Fredszaq
  • 3,091
  • 1
  • 18
  • 20
  • This doesn't work if you have a package with similar name installed. For example: jack and pipewire-jack – kamack38 Jul 01 '22 at 18:32
4

You can use the arch package management tool pacman.
As you can see in the Arch-Wiki, the -Qs option can be used to search within the installed packages.

If the package exists, pacman -Qs will exit with the exit-code 0, otherwise with the exit-code 1

You script might look like:

package=firefox
if pacman -Qs $package > /dev/null ; then
  echo "The package $package is installed"
else
  echo "The package $package is not installed"
fi

The > /dev/null pipe is used to suppress the printed output.

Random Citizen
  • 1,272
  • 3
  • 14
  • 28
3

I usually just do ls /bin | grep $package (replacing $package with the package I'm looking for). It's quick for the computer too.

It depends on the name of the package though, because this will list all of the installed executables that have $package in their name. Nevertheless, if you have executables installed with $package in their name, there's a big chance the package you're looking for is already installed.

Update

Here is a more accurate one:

package="lshw";
check="$(sudo pacman -Qs --color always "${package}" | grep "local" | grep "${package} ")";
if [ -n "${check}" ] ; then
    echo "${package} is installed";
elif [ -z "${check}" ] ; then
    echo "${package} is NOT installed";
fi;

Even better, how about turning it into a function?

There's 2 examples in the code below. You can use _install to install just one package. You can use _installMany to install as many packages as you want. I included both functions because _installMany is kind of complex, and looking at the slightly simpler _install function might help someone understand it.

#!/bin/bash
_isInstalled() {
    package="$1";
    check="$(sudo pacman -Qs --color always "${package}" | grep "local" | grep "${package} ")";
    if [ -n "${check}" ] ; then
        echo 0; #'0' means 'true' in Bash
        return; #true
    fi;
    echo 1; #'1' means 'false' in Bash
    return; #false
}

# `_install <pkg>`
_install() {
    package="$1";

    # If the package IS installed:
    if [[ $(_isInstalled "${package}") == 0 ]]; then
        echo "${package} is already installed.";
        return;
    fi;

    # If the package is NOT installed:
    if [[ $(_isInstalled "${package}") == 1 ]]; then
        sudo pacman -S "${package}";
    fi;
}

# `_installMany <pkg1> <pkg2> ...`
# Works the same as `_install` above,
#     but you can pass more than one package to this one.
_installMany() {
    # The packages that are not installed will be added to this array.
    toInstall=();

    for pkg; do
        # If the package IS installed, skip it.
        if [[ $(_isInstalled "${pkg}") == 0 ]]; then
            echo "${pkg} is already installed.";
            continue;
        fi;

        #Otherwise, add it to the list of packages to install.
        toInstall+=("${pkg}");
    done;

    # If no packages were added to the "${toInstall[@]}" array,
    #     don't do anything and stop this function.
    if [[ "${toInstall[@]}" == "" ]] ; then
        echo "All packages are already installed.";
        return;
    fi;

    # Otherwise, install all the packages that have been added to the "${toInstall[@]}" array.
    printf "Packages not installed:\n%s\n" "${toInstall[@]}";
    sudo pacman -S "${toInstall[@]}";
}

package="lshw";
_install "${package}";

packages=("lshw" "inkscape");
_installMany "${packages[@]}";
#Or,
_installMany "lshw" "inkscape"
Community
  • 1
  • 1
GreenRaccoon23
  • 3,603
  • 7
  • 32
  • 46
1

Try this:

isPackageInstalled() {
  pacman -Qi "$packageName" &> /dev/null
  echo $?
}

Using in a script is as simple as

if [ $(isPackageInstalled 'libssl') ]; then 
    # do things here
    echo 'Package libssl is installed'
fi
nathanchere
  • 8,008
  • 15
  • 65
  • 86
1

Personnaly, I use the following :

Append this to your ~/.bashrc, then source it:


havei() {
  package=$1
  if $(pacman -Qi $package &>/dev/null); then
    echo -e "\e[92m[  ] $package is installed \e[39m"
  else
    echo -e "\e[91m[ ❌ ] $package is not installed \e[39m"
  fi
}

Then you can simply use it in your everydays terminal:

havei firefox
SylvainB
  • 394
  • 7
  • 16
1

pacman -Q pkgName

if package is not installed, you will receive an error message:

error: pacmage 'pkgName' was not found

If package is installed, then a single line is printed:

pkgName x.y.z-r

pacman -Qi pkgName behaves the same way, only it prints detailed information about existing package.

Sergei G
  • 1,561
  • 3
  • 18
  • 26