6

I want to know which of my apps are available to install with brew cask command.
How can I do it?


Specification
What I want to do is to extract apps that are also available on brew-cask from all apps in /Applications and list up their package-names.

# /Applications
Alfred 4.app
App Store.app
AppCleaner.app
Automator.app
Be Focused Pro.app
BetterTouchTool.app
Bitdefender
Bluetooth Explorer.app
Books.app
Calculator.app
Calendar.app
CheatSheet.app
Chess.app
Clipy.app
...
# package names of apps available on brew-cask
alfred
appcleaner
bettertouchtool
calibre
cheatsheet
clip
...
solzard
  • 93
  • 1
  • 5
  • Can you elaborate a bit? Perhaps you're trying to view a list of *cask apps you have **already** installed, * or which currently installed apps can be *upgraded?* – vulpxn Apr 15 '20 at 00:35
  • All apps are manually installed (I knew brew-cask today). I want to know which of them are also available from brew-cask. – solzard Apr 15 '20 at 02:41
  • See if [this answer](https://stackoverflow.com/questions/38930492/list-of-installable-homebrew-casks) is useful, it sounds similar to what you're trying to do – vulpxn Apr 15 '20 at 02:46
  • @solzard I added an answer, I hope it helps you :) – Jérôme Apr 15 '20 at 18:53

3 Answers3

5

This is possible using Homebrew’s JSON API as well as some jq magic (brew install jq).

  1. Assuming none of your .app filenames contain a newline (very unlikely), you can get the list as a JSON array with a command combining ls and jq. However since we’ll use that list as a lookup it’s better to create an object instead:

    ls /Applications \
    | \grep '\.app$' \
    | jq -Rsc 'split("\n")[:-1]|map({(.):1})|add'
    

    This creates an object with each app as a key and 1 as a value (the value has no importance here). It outputs something like:

    {"1Password 7.app":1,"Amphetamine.app":1, "Firefox.app":1, …}
    
  2. You can list all 3,500+ installable casks using brew search --casks. In order to get a JSON describing one or more cask(s), including the .app they install, you can use brew cask info --json=v1 <cask> ….

    Combining these two, we can get a huge JSON describing all installable casks with:

    brew search --casks '' \
    | xargs brew info --cask --json=v2 \
    > allcasks.json
    

    This command takes ~10s on my machine so saving it in a file is a good idea.

  3. We can now filter this list to extract only the casks that install .apps from our earlier list:

    cat allcasks.json \
    | jq -r --argjson list '{…the list…}' '.[]|.[]|(.artifacts|map(.[]?|select(type=="string")|select(in($list)))|first) as $app|select($app)|"\(.token): \($app)"'
    

    Replace {…the list…} with the object we created earlier.

    This prints something like:

    1password: 1Password 7.app
    firefox: Firefox.app
    google-chrome: Google Chrome.app
    …
    

If you feel adventurous, here is a one-liner that does all these commands at once:

brew search --casks '' \
|xargs brew info --cask --json=v2 \
|jq -r --argjson l "$(ls /Applications|\grep '\.app$'|jq -Rsc 'split("\n")[:-1]|map({(.):1})|add')" '.[]|.[]|(.artifacts|map(.[]?|select(type=="string")|select(in($l)))|first) as $a|select($a)|"\(.token): \($a)"'

Breakdown of the jq command:

.[] # flatten the list
 |  # then for each element:
 .[] # flatten the list
 |  # then for each element:
   ( # take its artifacts
     .artifacts
      # then for each one of them
      | map(
         # take only arrays
         .[]?
         # select their string elements
         | select(type=="string")
         # that are also in the list
         | select(in($list)
       )
   )
   # take the first matching artifact
   | first)
   # and store it in $app
   as $app
 # then take only the elements with a non-empty $app
 | select($app)
 # and print their name (.token) and the app ($app)
 |"\(.token): \($app)"
aboy021
  • 2,096
  • 2
  • 23
  • 23
bfontaine
  • 18,169
  • 13
  • 73
  • 107
  • Looks like this no longer works with Homebrew `>=3.0.0` because the `brew cask` command no longer exists. Also, `brew info --cask` only accepts `v2` for the `json` flag, which seemingly does not work with the provided `jq` command: `$ brew search --casks | xargs brew info --cask --json=v2 > allcasks.json` and then `cat allcasks.json | jq -r --argjson list '{[…]}' '.[]|(.artifacts|map(.[]?|select(type=="string")|select(in($list)))|first) as $app|select($app)|"\(.token): \($app)"'` fails with `jq: error (at :1): Cannot index array with string "artifacts"`. – Philipp Bammes Feb 16 '21 at 06:03
  • Adding another ".[]" after the first one fixes the issue. The jq query becomes: `'.[]|.[]|(.artifacts|map(.[]?|select(type=="string")|select(in($list)))|first) as $app|select($app)|"\(.token): \($app)"'` – aboy021 Jan 21 '22 at 00:21
  • Just to clarify, the new command for getting the cask list is: `brew search --casks '' | xargs brew info --cask --json=v2 > allcasks.json` – aboy021 Jan 21 '22 at 00:24
  • @aboy021 could you edit the response to fix these issues? This is fresher in your mind than in mine ;) – bfontaine Jan 21 '22 at 08:35
  • 1
    I managed to get the following "one liner" working: ```brew search --casks --desc '' | sed -n -e 's/:.*$//p' | xargs brew info --cask --json=v2 | jq -r --argjson list "$(ls /Applications | \grep '\.app$' | jq -Rsc 'split("\n")[:-1]|map({(.):1})|add')" '.[]|.[]|(.artifacts|map(.[]?|select(type=="string")|select(in($list)))|first) as $app|select($app)|"\(.token): \($app)"' > matchingCasks.json``` I had to add the '--desc' flag to get around an odd: "Error: Cask '==>' is unavailable: No Cask with this name exists." and the 'sed' was added to remove the unnecessary tacked on description. – codeanpeace Feb 08 '22 at 06:38
0

You can use brew search on your terminal, like theses examples :

  • brew search vlc
  • brew search mamp
  • brew search slack
  • ...etc

You will get the available brew casks corresponding your search and you can install it with brew cask install mamp (replace mamp with your own app)

You can also go on this page https://formulae.brew.sh/cask/ to see all available casks.

If you app is already installed, you need to use brew cask install --force mamp to force the reinstallation and link your app already installed.

For more explanations, you can go here https://sourabhbajaj.com/mac-setup/Homebrew/Cask.html.

Jérôme
  • 978
  • 1
  • 9
  • 22
0

I need to do some minor modification to make this one liner work on my Mac.

HOMEBREW_VERSION: 4.0.28-5-g9f9ae1e
macOS: 13.4.1-x86_64

brew search --casks --desc '' --eval-all | sed -n -e 's/:.*$//p' | xargs brew info --cask --json=v2 | jq -r --argjson list "$(ls /Applications | \grep '\.app$' | jq -Rsc 'split("\n")[:-1]|map({(.):1})|add')" '.[]|.[]|(.artifacts|.[]|map(.[]?|select(type=="string")|select(in($list)))|first) as $app|select($app)|"\(.token): \($app)"' > matchingCasks.json