11

How can I create a bash script that checks if a program is already installed, and if it isn't, installs it?

Thanks for your help.

Here's the code I have so far:

#/bin/bash

PS3="choose an option"

select opcion in "Installing_Youtube"  "exit"

do

    case $opcion in


        "Installing_Youtube")

            youtube-dl > /usr/bin
            if [ $? -eq 127 ] ; then
                echo "installing youtube"
                 apt-get update
                 apt-get install youtube-dl
                mkdir Videos
            else
                echo "Youtube already installed"
            fi

        ;;


        "exit")
            exit
Elder Geek
  • 36,023
  • 25
  • 98
  • 183
  • 10
    Do you intend to overwrite /usr/bin ? – D. Ben Knoble Dec 23 '18 at 00:51
  • 1
    Are you differentiating between package names, and executable filenames? Or want to check both? Only George's answer currently checks for executables – Xen2050 Dec 23 '18 at 03:27
  • Why do you want to check it? What's the purposed use of this script? – Braiam Dec 23 '18 at 11:11
  • @Braiam At least with apt, installing an already installed package will change its status from automatic to manual if it was only installed as a dependency of another package. If that other package is later removed, this package will no longer be marked for auto removal. I have a script to install an edited list of packages from a previous install into a new one. This technique keeps it from making a mess of the new system. – Joe Dec 27 '18 at 00:42
  • @Joe which is a bad solution. You should instead just get the list of installed packages with apt-mark showmanual then installing with something like apt-get install "$(< package.list)". – Braiam Dec 27 '18 at 13:02
  • @Braiam That sounds like a good idea. But, I just ran apt-mark showmanual | wc -l on my current system and it returned 2033 packages, many of which I am sure I never intentionally installed manually including things like apparmor and apport which I'm sure would have been installed by default. dpkg -l | wc -l only found 3844 total and I don't modify half of my system. Maybe this should be a separate question. – Joe Dec 28 '18 at 01:02
  • @Joe those are marked as installed manually on installation by Ubuntu, since Ubuntu tends to not have a single meta-package that installs everything. – Braiam Dec 28 '18 at 13:03
  • Then, testing if installed isn't necessary using your method, but it still might speed things up a bit and it would eliminate a ton of noise messages about packages already being installed at the current version. – Joe Dec 28 '18 at 13:46

5 Answers5

13

you can do this:

dpkg -s <packagename> &> /dev/null

then check exit status.only if the exit status of the above command was equal to 0 then the package installed.

so:

   #!/bin/bash

    echo "enter your package name"
    read name

    dpkg -s $name &> /dev/null  

    if [ $? -ne 0 ]

        then
            echo "not installed"  
            sudo apt-get update
            sudo apt-get install $name

        else
            echo    "installed"
    fi
Hossein
  • 171
  • 7
  • Except it doesn't? What happened to the line with sudo apt install $name? The command needs to go on the next line... Otherwise, nice work... – Zanna Dec 22 '18 at 21:30
  • 4
    Note that software could be installed in a variety of ways, and dpkg is only relevant for installed debian packages. In OP's particular case, youtube-dl for instance could be also installed via python's package manager pip – Sergiy Kolodyazhnyy Dec 22 '18 at 21:36
  • 3
    Why not if dpkg -s “$name” &> /dev/null ; then ? Same effect, cleaner/clearer imo. – D. Ben Knoble Dec 23 '18 at 00:52
  • indeed, checking the exit status is exactly what if does... – Zanna Dec 23 '18 at 10:35
5

This line of command will check using the which program and will return 0 if installed and 1 if not:

which apache | grep -o apache > /dev/null &&  echo 0 || echo 1

Of course you will use it in this manner in your script:

which "$1" | grep -o "$1" > /dev/null &&  echo "Installed!" || echo "Not Installed!"

A simple usage would be:

#!/usr/bin/env bash
set -e

function checker() { 
        which "$1" | grep -o "$1" > /dev/null &&  return 0 || return 1 
}

if checker "$1" == 0 ; then echo "Installed"; else echo "Not Installed!"; fi

Note several things:

  1. You will have to deal with dependenciy issues while installing
  2. To avoid interaaction with script during install see here for examples.
  3. You can catch the return values from that function an use it to decide whether to install or not.
George Udosen
  • 36,677
  • which is super non-portable. I frequently use command -v instead, but it depends heavily on the type of name you’re looking for (alias, function, executable, &c.) – D. Ben Knoble Dec 23 '18 at 00:54
  • Super non-portable for a question that is for an Ubuntu machine? This is isn't Unix & Linux site! If i were answering it on Unix & Linux site that would be a different matter! – George Udosen Dec 23 '18 at 13:15
4

Here's a function I wrote for the purpose that I use in my scripts. It checks to see if the required package is installed and if not, prompts the user to install it. It requires a package name as a parameter. If you don't know the name of the package a required program belongs to you can look it up. Information on that available here.

function getreq {
dpkg-query --show  "$1"
if [ "$?" = "0" ];
then
    echo "$1" found
else
    echo "$1" not found. Please approve installation.
    sudo apt-get install "$1"
    if [ "$?" = "0" ];
    then echo "$1" installed successfully.
    fi
fi
}
Elder Geek
  • 36,023
  • 25
  • 98
  • 183
2

One easy way to check for installed packages using apt-mark:

apt-mark showinstall will list all packages marked install (already installed, or queued for installation). After that, it's a simple matter of grepping the package(s) you care about.

Example: apt-mark showinstall | grep -q "^$PACKAGE_NAME$" && echo "installed" || echo "not"

user535733
  • 62,253
2

Why do you want to check it in the first place? Unless you have a good reason for it, don't do it, just apt-get install package over. If it's already installed it will be updated if there is a newer version available, if it is installed and it is up to date, nothing will happen. In case you have some configuration that needs to be applied, there are other options, like building an configuration package which depends on the package or using configuration management software like ansible.

Zanna
  • 70,465
user2567875
  • 129
  • 2
  • 1
    Something will often happen: At least with apt, installing an already installed package will change its status from automatic to manual if it was only installed as a dependency of another package. If that other package is later removed, this package will no longer be marked for auto removal. I have a script to install an edited list of packages from a previous install into a new one. This technique keeps it from making a mess of the new system. – Joe Dec 27 '18 at 00:45
  • This is an irrelevant answer. It is like asking why do you want to add 5 Dollar for apple juice and 6 dollars for bread, just give the guy a 20 and he will give you back the right amount. – Max Feb 16 '22 at 07:22