74

I'm installing a set of softwares/packages/formulas via homebrew with command like

brew install <formula1>
...
brew cask install <formula2>
...

I wonder if it's a good idea to verify if the softwares <formula1>, ..., <formula2>, ... are already installed and only trigger the above commands for the ones NOT already installed. If so, how?

1
  • 1
    If it's not critical to get this info from Homebrew, and you don't care how it was installed, which <programname> is faster than brew list <programname>. Jan 3, 2022 at 21:53

4 Answers 4

96

you could do something like this:

brew list <formula1> || brew install <formula1>

This will error on list and continue with install if not installed otherwise it will just list package files. (one could modify this further as a function or alias in .bashrc to make it easier to type)

3
  • 1
    How can this be done in a Brewfile?
    – Jack Moody
    Jan 28, 2019 at 16:04
  • 1
    @JackMoody It sounds like what you want to do is add it as a dependency in the brew file using depends_on
    – svangordon
    Oct 2, 2020 at 1:52
  • 3
    can confirm. brew list [email protected] &>/dev/null || brew install [email protected]; works.
    – airtonix
    Feb 4, 2021 at 0:28
32

It should also be noted that you can type brew info <formula> which will tell you whether or not a formula is installed. You can parse the response for "Not installed" and then run the installer if it finds the string.

4
  • 3
    the disadvantage of brew info <formula> is that it loads very slowly, as it has to fetch the statistics of the formula from the Internet. If you use brew list <formula> | grep "No such keg" (or something similar), the result will be displayed much faster.
    – Raptor
    Oct 13, 2020 at 14:38
  • 1
    brew info always has a exit code 0. so it's useless. brew list [email protected] &>/dev/null || brew install [email protected]; works because it returns 1 when there's nothing found.
    – airtonix
    Feb 4, 2021 at 0:30
  • 1
    @airtonix Just because it always has an exit code of 0 doesn't make it useless. As I mention in my post this method requires that you parse the response. Feb 4, 2021 at 17:05
  • 2
    @JoshCorreia nah it's useless. you want to know it failed or not. this is why exit codes exist.
    – airtonix
    Feb 27, 2021 at 3:52
7

Building on the earlier answers, but packed into a ready to use function without all the homebrew logging:

brew_install() {
    echo "\nInstalling $1"
    if brew list $1 &>/dev/null; then
        echo "${1} is already installed"
    else
        brew install $1 && echo "$1 is installed"
    fi
}

brew_install "ripgrep"
2

In similar vein to Hans Fredric, here is a snippet I actually use myself. The funny looking <(cmd) is Bash command substitution.

alias strip-empty="egrep -v '^\s*$'"
NOT_INSTALLED=$(comm -23 <(sort < apps.local) <( brew list --versions | awk '{print $1}' ) | strip-empty)
while read FORMULA; do
    brew install "$FORMULA"
done <<< "$NOT_INSTALLED"

Here, apps.local is just a list of apps to install, one per line. The improvement over just looping over each app and trying something like brew_install basically comes down to speed. Invoking brew list is slow (like up to a second), so I just do the test once by listing out all installed apps. The difference is very noticeable if you have > 5 apps.

If you need something with the same speed, but that works equally well with apps installed using a cask, you need something more elaborate (like this).

3
  • The alias is probably not required. Also, if you don't need $NOT_INSTALLED later, you could just run comm ... | awk ... | while ....
    – nohillside
    Sep 2, 2021 at 8:10
  • Is absolutelyl not needed, but makes for less magic when reading it in half a year. You know, Dr. Bob: ExtractMethod to avoid needless comment. No need to invoke the RegExp cortex of the brain. And the piped version makes for much harder debugging when you want to change something - I went there first :-)
    – oligofren
    Sep 2, 2021 at 8:16
  • Agreed. I probably would include the grepping in the awk part but that's for sure is a matter of personal taste :-)
    – nohillside
    Sep 2, 2021 at 8:42

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .