Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

List up my apps installable with brew-cask

Tags:

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
...
like image 481
solzard Avatar asked Apr 14 '20 23:04

solzard


1 Answers

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)"
like image 63
bfontaine Avatar answered Sep 30 '22 19:09

bfontaine