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
...
This is possible using Homebrew’s JSON API as well as some jq
magic (brew install jq
).
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, …}
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.
We can now filter this list to extract only the casks that install .app
s 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)"