85

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
  • 3
    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>. Commented Jan 3, 2022 at 21:53

5 Answers 5

108

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)

4
  • 1
    How can this be done in a Brewfile? Commented 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 Commented Oct 2, 2020 at 1:52
  • 5
    can confirm. brew list [email protected] &>/dev/null || brew install [email protected]; works. Commented Feb 4, 2021 at 0:28
  • 3
    Works, but may be quite slow. On my machine, brew list gradle >/dev/null takes over three seconds, because brew list prints all files (over 20K for Gradle) when stdout is not an interactive shell. :-( Alternative: brew list --versions gradle >/dev/null. On my box, this only takes 0.5 seconds. Commented Sep 10, 2024 at 20:15
34

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. Commented 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. Commented 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. Commented 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. Commented 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 .... Commented 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 :-) Commented 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 :-) Commented Sep 2, 2021 at 8:42
0

Check if it's installed and up-to-date.

brew list codespell && ( brew outdated codespell || brew upgrade codespell ) || brew install codespell 

This is as simple as I could get it.

One reason I wanted to check if the package is outdated first before running brew upgrade is because brew upgrade will return a Warning when it is up-to-date, like:

Warning: codespell 2.4.1 already installed 

This isn't a big deal in the console but it appears in the Annotations of Github Actions which I didn't like.

Logic

  • If it's not installed
    • Install it with brew install
  • If it is installed
    • If it is outdated
      • Upgrade with brew upgrade
    • If it is not outdated
      • Return with no error code.

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.