The open source Homebrew package manager gives Mac users access to Unix command-line utilities that Apple left out — and a lot more Credit: Thinkstock In the beginning was the command-line. That’s true of almost all operating systems, but somewhere along the way a graphical user interface became the “face” of the computer, and only old hackers or initiates even knew how to open a command-line console or terminal. Many Mac users can manage marvelously without ever opening the Terminal app, much less typing commands into the Bash shell. If you spend your day editing still images with Lightroom, the MacOS command line likely has little utility for you. More technical users, and especially software developers, need to work in the shell at least occasionally, if not on a daily basis. Technical users with some Unix or Linux background will discover that not all the usual utilities are installed in MacOS as it comes from the factory, even though at its heart MacOS is a BSD Unix system. As a software developer and a software reviewer, I often run into this issue. The first time it happened I was following online installation instructions that purported to work on Linux and Linux-like systems (such as Mac OS X, as it was known at the time), but had only actually been tested on one or two distros of Linux. The installation command provided was based on <a href="https://www.gnu.org/software/wget/manual/wget.html#Overview" rel="nofollow">wget</a>, a utility for non-interactive download of files from the web. Unfortunately for me, wget doesn’t come installed on a Mac, although the somewhat similar <a href="https://manpages.debian.org/stretch/curl/curl.1.en.html" rel="nofollow">curl</a> utility does. Translating wget options to curl options was an annoying extra step I didn’t need; the lack of recursive downloads in curl was a complete showstopper for downloading the HTML documentation. Apple has no official mechanisms for adding new command-line utilities. What it has for a package manager is the App Store, but that’s only for applications (apps). When I searched the web for “wget not found mac” I quickly discovered that there were several ways to solve my problem, including building wget from the source code. Of these, the most frequently recommended was Homebrew. What is Homebrew? Homebrew calls itself “The missing package manager for MacOS” (emphasis mine). That’s pithy, but a little cavalier. Homebrew is certainly a package manager for MacOS, but there are others, such as MacPorts and Fink. And for that matter, the App Store is a package manager, albeit specialized to, um, App Store apps. Nevertheless, Homebrew is the most popular third-party package manager for MacOS, and supplies functionality missing from the App Store. You can use Homebrew (brew) to install, uninstall, and upgrade any of thousands of “formulae” (i.e. package definitions) from its core public repository, plus any tap repositories you care to use. You can also use the Homebrew cask facility (brew-cask) as a way to install, uninstall, and upgrade precompiled MacOS binaries (such as apps, but not App Store apps) from the command line. If you wish, you can create your own Homebrew packages and write your own Homebrew formulae. Install Homebrew Since Homebrew itself is only for MacOS, it has fairly simple installation instructions — at least, if your OS version is more recent than OS X Lion 10.7. Homebrew basically just runs a Ruby script after downloading it from GitHub; you’ll note in the screenshot below that Homebrew uses curl for the download, not wget, for reasons I discussed earlier. IDG It’s easy to install Homebrew. Just follow the instructions on the website. Homebrew also confines itself to Ruby code supported by the Ruby version that ships with the oldest OS X version that it supports, 10.5 Leopard. /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" It is possible that the Homebrew installation will ask you to install Xcode or the Command Line Tools for Xcode. Whether it does and which it suggests would be dependent on your OS version and the versions of the C and C++ compilers installed on your system. According to the Homebrew installation page, if you have an older version of Mac OS X (Lion 10.7 or before), then you need to add the --insecure argument (or equivalently -k, making the full argument list -fsSLk) to the curl command. That’s because the version of curl on your system won’t successfully talk to GitHub using HTTPS. Homebrew will fix that if you install it and then ask it to update itself and its dependencies with brew update. If you download the install script and read it, you’ll see it includes logic to abort if the Mac OS X version is less than 10.5. If that triggers, the script will refer you to TigerBrew, which is an experimental fork of Homebrew that adds support for PowerPC Macs and Macs running Tiger. There is also a “we don’t support this version” warning that will trigger for MacOS versions that are too old or too new, currently set at 10.11 and 10.13. That doesn’t mean Homebrew won’t work on those versions; it mostly means that the developers don’t test against them. Use Homebrew to install a package As a basic example, let’s try installing wget with Homebrew. First, launch Terminal. The installation command is just as listed in the image above: brew install wget. On my machine, it produced the rather lengthy output below. Note that the installation began with an auto-update of Homebrew, then installed wget’s dependencies, and then finally installed wget. Updating Homebrew... ==> Homebrew is run entirely by unpaid volunteers. Please consider donating: https://github.com/Homebrew/brew#donations ==> Auto-updated Homebrew! Updated 2 taps (homebrew/core, homebrew/cask). ==> New Formulae amtk kustomize range-v3 aws-okta libsignal-protocol-c safe badtouch lsusb serverless black luarocks sfst cash-cli micronaut sonarqube-lts docker-credential-helper-ecr miniserve squashfuse docker-machine-driver-hyperkit pcapplusplus thors-serializer fauna-shell perltidy weaver gambit petsc-complex wiremock-standalone gptfdisk pijul wskdeploy gradio prettier xcodegen helmfile pulumi xsimd infrakit pyside yarn-completion kubernetes-service-catalog-client python-yq zlog ==> Updated Formulae automake ✔ fbi-servefiles libpcap puzzles cmake ✔ fd libphonenumber py2cairo cockroach ✔ fdclone libpq py3cairo eigen ✔ fdroidserver libpqxx pyenv libpng ✔ feh libpst pyinvoke numpy ✔ ffmpeg libqalculate qbs openssl ✔ ffmpeg@2.8 librdkafka qcachegrind subversion ✔ fibjs librealsense qemu abcde file-formula libsoup qjackctl abcm2ps file-roller libssh qpdf ace fio libtensorflow qtkeychain acpica firebase-cli libtorrent-rasterbar quicktype activemq flintrock libtrace rabbitmq adr-tools flow libuv radare2 advancemame fluent-bit libvirt rakudo-star agda flyway libwps rancher-cli aircrack-ng fmt libxkbcommon raylib allure fn lighttpd re2 amazon-ecs-cli folly link-grammar reattach-to-user-namespace angband fonttools linkerd redis angle-grinder fortio liquibase rename angular-cli fq liquigraph restic annie freeciv llvm riemann-client ansible freeimage lmod ripgrep ansible-cmdb freetds log4cplus rocksdb ansiweather fribidi logtalk roll ant frugal lrzsz root ant@1.9 fruit lsof roswell apache-arrow fselect lua rsyslog apache-arrow-glib fuseki lua@5.1 rtv apache-flink futhark lxc ruby-build app-engine-python fwknop lynis ruby-install appscale-tools fwup lynx rust arangodb gammaray macvim rustup-init argyll-cms gauche mafft s-nail ark gcc mapcrafter s3cmd arm-linux-gnueabihf-binutils gdb mariadb s3fs armadillo gdbm mariadb@10.0 samtools arpack gegl mariadb@10.1 sane-backends artifactory geoipupdate mariadb@10.2 sbcl asdf geos math-comp sbt ask-cli geoserver mbedtls sbtenv ats2-postiats get_iplayer mdds sccache aws-elasticbeanstalk giflib mdp sceptre aws-sdk-cpp gimme megatools schema-evolution-manager awscli git-annex memcached schismtracker azure-cli git-archive-all menhir scrcpy b2-tools git-extras mercurial selenium-server-standalone babel git-ftp meson sfk babl git-lfs metabase shairport-sync bacula-fd git-quick-stats micro shellharden ballerina gitbucket mikutter shfmt bareos-client giter8 mill shibboleth-sp bartycrouch gitlab-gem mingw-w64 singular bat gitlab-runner minimal-racket sipp bats-core gjstest mint skaffold bazel glib mitmproxy skafos bcftools glib-networking mkcert skinny bdw-gc globus-toolkit mkdocs skktools bear glslviewer mkl-dnn sleuthkit beast gmt@4 mkvtoolnix snakemake bench gnatsd mlkit sonarqube bettercap gnome-builder modd sord bgpstream gnome-latex modules spdlog binaryen gnu-prolog monero sphinx-doc bind gnumeric mongo-c-driver spotbugs binutils gnupg mongo-cxx-driver sqlmap bit gnupg@1.4 mongodb sqoop bitcoin gnuradio mongodb@3.6 squid bitrise gnutls mongoose sratoolkit bitwarden-cli go-bindata mono ssh-copy-id blockhash go-jira mosquitto ssh-permit-a38 bowtie2 go-statik mpd sshguard buildifier gobuster mpop sshrc byobu gocryptfs mr sshtrix byteman goenv mrtg sslsplit bzt goffice msgpack sslyze cabextract gomplate msitools stanford-ner cake goreleaser mujs stanford-parser camlp4 gosu mutt stern camlp5 gpac mvtools stone-soup capstone gr-osmosdr mypy suite-sparse cargo-completion gradle mysql sundials cassandra grafana mysql-client suricata ccextractor grails mysql@5.5 swift ccrypt grakn mysql@5.6 swift-protobuf ceres-solver graphite2 mysql@5.7 swiftformat certbot groonga nagios swiftlint cfr-decompiler groovy nativefier syncthing cglm groovysdk naturaldocs sysdig chakra grpc nco talloc charm grunt-completion neo4j tarantool checkstyle gsoap neomutt taskell chrome-cli gst-editing-services neovim tbox chronograf gst-libav net-snmp telegraf cimg gst-plugins-bad nginx teleport circleci gst-plugins-base nifi tepl citus gst-plugins-good nnn termius ckan gst-plugins-ugly node terraform clamav gst-python node-build terraform_landscape clblast gst-rtsp-server node@6 terragrunt clingo gst-validate node@8 the_platinum_searcher clojure gstreamer nodeenv the_silver_searcher closure-compiler gtk-vnc npth tig cmark-gfm guile nsd tiger-vnc collectd gupnp ntl tippecanoe commandbox gutenberg ntp titlecase composer hadolint nuget tkdiff conan hadoop nuxeo tmate confluent-oss hana nvc tmux-xpanes confuse haproxy nyancat todolist conjure-up harfbuzz ocaml tomcat@8 consul hashcat ocaml-num tor convox hcloud ocamlbuild tox coq heroku ocamlsdl traefik corsixth hexgui ocrmypdf trafficserver couchdb hh octave translate-shell cquery highlight odpi trash credstash hive ola travis creduce hlint open-mpi triton cromwell hopenpgp-tools openapi-generator ttfautohint cryptol hss openblas tty-solitaire crystal htslib opencoarrays tup csvkit httpd opendetex twarc csvprintf hub openimageio twoping curl hugo opensaml txr cython hyperfine openshift-cli typescript dar hyperscan openssh u-boot-tools darksky-weather i2p openssl@1.1 ubertooth dartsim icdiff openvdb uhd dateutils igv osc unixodbc dbus imagemagick osmium-tool upx dcd imagemagick@6 osquery urh dcos-cli imageoptim-cli overmind uriparser ddclient influxdb p11-kit utf8proc deark ios-webkit-debug-proxy packer util-linux dep ipfs paket uwsgi dependency-check ipython pandoc v8 dhall-json ipython@5 pango vala di isl parallel vapoursynth diff-pdf jboss-forge pari vault diffoscope jenkins passenger vcftools discount jenkins-job-builder pazpar2 vdirsyncer distcc jenkins-lts pc6001vx vegeta dita-ot jfrog-cli-go pcb2gcode verilator django-completion jhipster pdftoedn vert.x dlib jlog pdftoipe vim dmd joplin pegtl vips dnscrypt-proxy jpeg-archive percona-server-mongodb virtuoso dnsdist jpeg-turbo percona-server@5.6 vnu docfx json-fortran percona-toolkit vowpal-wabbit docker jsonnet perl-build vrpn docker-completion juju pgbouncer vsts-cli docker-compose jump pgcli wabt docker-compose-completion kafka pgplot wandio docker-credential-helper kerl pgpool-ii watchexec dovecot kitchen-sync php webdis draco knot php-code-sniffer webpack dropbear knot-resolver php-cs-fixer webtorrent-cli druid kompose php@5.6 weechat dscanner kontena php@7.0 whois dtc kops php@7.1 wine duck kotlin phplint winetricks duply kube-aws phpmyadmin wiredtiger dwarfutils kubecfg phpunit wireguard-tools dxpy kubectx picard-tools wireshark dynare kubeless pilosa wp-cli e2fsprogs kubernetes-cli pkcs11-helper wtf eccodes kubernetes-helm plantuml wxmac efl lablgtk platformio xapian elektra landscaper pmd xml-security-c elixir latex2rtf pony-stable xml-tooling-c elm lensfun ponyc xmrig elvish lf poppler xonsh emscripten libatomic_ops postgresql xtensor ephemeralpg libcouchbase postgresql@9.4 yafc erlang libdazzle postgresql@9.5 yara erlang@19 libdill postgresql@9.6 yarn erlang@20 libdvbpsi pre-commit yaz etcd libextractor prest ykman ethereum libfixbuf presto yle-dl exercism libgit2 primesieve you-get exomizer libgpg-error prometheus youtube-dl expat libgphoto2 proselint yq exploitdb libgsf protobuf-c zabbix f3 libhdhomerun protobuf@2.6 zanata-client faas-cli libical proxychains-ng zebra fabric libmagic pspg zero-install fakeroot libomp pulseaudio zimg fastqc libosmium pushpin znc ==> Deleted Formulae artifactory-cli-go boot2docker-completion ghc@8.0 gpg-agent wry boot2docker dirmngr gnupg@2.0 node@4 ==> Installing dependencies for wget: gettext, libunistring, libidn2, openssl ==> Installing wget dependency: gettext ==> Downloading https://homebrew.bintray.com/bottles/gettext-0.19.8.1.high_sierra.bottle.tar.gz ######################################################################## 100.0% ==> Pouring gettext--0.19.8.1.high_sierra.bottle.tar.gz ==> Caveats gettext is keg-only, which means it was not symlinked into /usr/local, because macOS provides the BSD gettext library & some software gets confused if both are in the library path. If you need to have gettext first in your PATH run: echo 'export PATH="/usr/local/opt/gettext/bin:$PATH"' >> ~/.bash_profile For compilers to find gettext you may need to set: export LDFLAGS="-L/usr/local/opt/gettext/lib" export CPPFLAGS="-I/usr/local/opt/gettext/include" ==> Summary 🍺 /usr/local/Cellar/gettext/0.19.8.1: 1,935 files, 16.9MB ==> Installing wget dependency: libunistring ==> Downloading https://homebrew.bintray.com/bottles/libunistring-0.9.10.high_sierra.bottle.tar.gz ######################################################################## 100.0% ==> Pouring libunistring--0.9.10.high_sierra.bottle.tar.gz 🍺 /usr/local/Cellar/libunistring/0.9.10: 54 files, 4.4MB ==> Installing wget dependency: libidn2 ==> Downloading https://homebrew.bintray.com/bottles/libidn2-2.0.5.high_sierra.bottle.tar.gz ######################################################################## 100.0% ==> Pouring libidn2--2.0.5.high_sierra.bottle.tar.gz 🍺 /usr/local/Cellar/libidn2/2.0.5: 68 files, 668.6KB ==> Installing wget dependency: openssl ==> Downloading https://homebrew.bintray.com/bottles/openssl-1.0.2p.high_sierra.bottle.tar.gz ######################################################################## 100.0% ==> Pouring openssl--1.0.2p.high_sierra.bottle.tar.gz ==> Caveats A CA file has been bootstrapped using certificates from the SystemRoots keychain. To add additional certificates (e.g. the certificates added in the System keychain), place .pem files in /usr/local/etc/openssl/certs and run /usr/local/opt/openssl/bin/c_rehash openssl is keg-only, which means it was not symlinked into /usr/local, because Apple has deprecated use of OpenSSL in favor of its own TLS and crypto libraries. If you need to have openssl first in your PATH run: echo 'export PATH="/usr/local/opt/openssl/bin:$PATH"' >> ~/.bash_profile For compilers to find openssl you may need to set: export LDFLAGS="-L/usr/local/opt/openssl/lib" export CPPFLAGS="-I/usr/local/opt/openssl/include" For pkg-config to find openssl you may need to set: export PKG_CONFIG_PATH="/usr/local/opt/openssl/lib/pkgconfig" ==> Summary 🍺 /usr/local/Cellar/openssl/1.0.2p: 1,793 files, 12.3MB ==> Installing wget ==> Downloading https://homebrew.bintray.com/bottles/wget-1.19.5.high_sierra.bottle.tar.gz ######################################################################## 100.0% ==> Pouring wget--1.19.5.high_sierra.bottle.tar.gz 🍺 /usr/local/Cellar/wget/1.19.5: 50 files, 3.7MB ==> Caveats ==> gettext gettext is keg-only, which means it was not symlinked into /usr/local, because macOS provides the BSD gettext library & some software gets confused if both are in the library path. If you need to have gettext first in your PATH run: echo 'export PATH="/usr/local/opt/gettext/bin:$PATH"' >> ~/.bash_profile For compilers to find gettext you may need to set: export LDFLAGS="-L/usr/local/opt/gettext/lib" export CPPFLAGS="-I/usr/local/opt/gettext/include" ==> openssl A CA file has been bootstrapped using certificates from the SystemRoots keychain. To add additional certificates (e.g. the certificates added in the System keychain), place .pem files in /usr/local/etc/openssl/certs and run /usr/local/opt/openssl/bin/c_rehash openssl is keg-only, which means it was not symlinked into /usr/local, because Apple has deprecated use of OpenSSL in favor of its own TLS and crypto libraries. If you need to have openssl first in your PATH run: echo 'export PATH="/usr/local/opt/openssl/bin:$PATH"' >> ~/.bash_profile For compilers to find openssl you may need to set: export LDFLAGS="-L/usr/local/opt/openssl/lib" export CPPFLAGS="-I/usr/local/opt/openssl/include" For pkg-config to find openssl you may need to set: export PKG_CONFIG_PATH="/usr/local/opt/openssl/lib/pkgconfig" When I test the new installation with wget --help, it tells me it is GNU Wget 1.19.5 and gives me the help text. The command man wget also works at this point. Running which wget tells me that the installation is at /usr/local/bin/wget, and ls -l /usr/local/bin/wget tells me that it’s a pointer to ../Cellar/wget/1.19.5/bin/wget. That is consistent with what Homebrew reported during the installation. As an aside, note that wget will only retrieve URLs that give it permission, and it respects the Robot Exclusion Standard (/robots.txt). So, for example, if you try to download a site that doesn’t want to be scraped, you’ll get a 403 Forbidden error. $ wget pcpitstop.com --2018-08-27 11:18:20-- http://pcpitstop.com/ Resolving pcpitstop.com (pcpitstop.com)... 104.20.82.39, 104.20.83.39 Connecting to pcpitstop.com (pcpitstop.com)|104.20.82.39|:80... connected. HTTP request sent, awaiting response... 301 Moved Permanently Location: http://www.pcpitstop.com/ [following] --2018-08-27 11:18:20-- http://www.pcpitstop.com/ Resolving www.pcpitstop.com (www.pcpitstop.com)... 104.20.83.39, 104.20.82.39 Connecting to www.pcpitstop.com (www.pcpitstop.com)|104.20.83.39|:80... connected. HTTP request sent, awaiting response... 403 Forbidden 2018-08-27 11:18:20 ERROR 403: Forbidden. By contrast, curl will blithely download the single pages you request, whether or not the site has robot exclusions. curl http://www.pcpitstop.com will output a bunch of HTML from the site’s home page. As an example where wget will work fine, consider this example from the Gnu wget documentation: wget ftp://ftp.gnu.org/pub/gnu/ links index.html I tried it, and the wget part worked, but the links command wasn’t found: $ wget ftp://ftp.gnu.org/pub/gnu/ --2018-08-27 11:35:34-- ftp://ftp.gnu.org/pub/gnu/ => ‘.listing’ Resolving ftp.gnu.org (ftp.gnu.org)... 208.118.235.20 Connecting to ftp.gnu.org (ftp.gnu.org)|208.118.235.20|:21... connected. Logging in as anonymous ... Logged in! ==> SYST ... done. ==> PWD ... done. ==> TYPE I ... done. ==> CWD (1) /pub/gnu ... done. ==> PASV ... done. ==> LIST ... done. .listing [ <=> ] 24.87K --.-KB/s in 0.01s 2018-08-27 11:35:34 (2.11 MB/s) - ‘.listing’ saved [25466] Removed ‘.listing’. Wrote HTML-ized index to ‘index.html’ [37782]. Martins-Retina-MacBook:~ martinheller$ links index.html -bash: links: command not found What should you do to install links? Your first guess is probably correct: $ brew install links Updating Homebrew... ==> Auto-updated Homebrew! Updated 2 taps (homebrew/core, homebrew/cask). ==> New Formulae eslint geogram go@1.10 json11 luit ==> Updated Formulae go ✔ diff-pdf gmt@4 libphonenumber pdal tomcat hdf5 ✔ dynare godep libtensorflow pdftoedn tomcat-native angular-cli elasticsearch@5.6 goenv mdcat pdftoipe tomcat@7 armadillo elixir gromacs meson perl-build tomcat@8 augeas feedgnuplot hcloud minizinc plantuml vtk awscli field3d iso-codes mkcert poppler yubico-piv-tool bwfmetaedit flann jenkins nco prettier zsh-completions caffe folly jenkins-job-builder ncview s6 cimg git-cola kallisto netcdf saxon ckan git-quick-stats kibana@5.6 nghttp2 sratoolkit convox gitlab-runner libbi octave svtplay-dl dartsim gmt libmatio pcl thors-serializer ==> Downloading https://homebrew.bintray.com/bottles/links-2.16.high_sierra.bottle.tar.gz ######################################################################## 100.0% ==> Pouring links--2.16.high_sierra.bottle.tar.gz 🍺 /usr/local/Cellar/links/2.16: 19 files, 1.8MB Martins-Retina-MacBook:~ martinheller$ links index.html By the way, an alternative to links on MacOS is simply to open the HTML file in your browser. From the command line, that’s open index.html. Query Homebrew You saw above that Homebrew will list the recipes that have changed in its directory after an automatic update and will flag the installed recipes that have changed in bold with green checkmarks ✔. You can also ask Homebrew to show you what it currently has installed: $ brew ls apr cockroach gflags jpeg links pcre subversion apr-util delve glog leveldb lmdb perl swig autoconf eigen go libidn2 nmap pkg-config szip automake fontconfig gperftools libpng numpy readline webp boost freetype graphviz libtiff opencv scons wget boost-python gd hdf5 libtool openexr snappy cmake gettext ilmbase libunistring openssl sqlite Any option flags are passed to ls, for example: $ brew ls -l total 0 drwxr-xr-x 3 martinheller admin 96 Apr 9 16:37 apr drwxr-xr-x 3 martinheller admin 96 Apr 9 16:37 apr-util drwxr-xr-x 3 martinheller admin 96 Oct 19 2016 autoconf drwxr-xr-x 3 martinheller admin 96 Oct 19 2016 automake drwxr-xr-x 4 martinheller admin 128 Jan 5 2017 boost drwxr-xr-x 4 martinheller admin 128 Jan 5 2017 boost-python drwxr-xr-x 4 martinheller admin 128 Dec 9 2016 cmake drwxr-xr-x 3 martinheller admin 96 Dec 15 2017 cockroach drwxr-xr-x 4 martinheller admin 128 Jul 5 14:03 delve drwxr-xr-x 4 martinheller admin 128 Dec 9 2016 eigen drwxr-xr-x 3 martinheller admin 96 Jan 5 2017 fontconfig drwxr-xr-x 3 martinheller admin 96 Jan 5 2017 freetype drwxr-xr-x 3 martinheller admin 96 Jan 5 2017 gd drwxr-xr-x 3 martinheller staff 96 Aug 24 14:33 gettext drwxr-xr-x 4 martinheller admin 128 Dec 9 2016 gflags drwxr-xr-x 4 martinheller admin 128 Dec 9 2016 glog drwxr-xr-x 3 martinheller admin 96 Jul 5 14:03 go drwxr-xr-x 3 martinheller admin 96 Oct 19 2016 gperftools drwxr-xr-x 4 martinheller admin 128 Jan 5 2017 graphviz drwxr-xr-x 4 martinheller admin 128 Jan 5 2017 hdf5 drwxr-xr-x 3 martinheller admin 96 Oct 19 2016 ilmbase drwxr-xr-x 3 martinheller admin 96 Oct 19 2016 jpeg drwxr-xr-x 3 martinheller admin 96 Oct 19 2016 leveldb drwxr-xr-x 3 martinheller staff 96 Aug 24 14:34 libidn2 drwxr-xr-x 5 martinheller admin 160 Jan 5 2017 libpng drwxr-xr-x 4 martinheller admin 128 Dec 9 2016 libtiff drwxr-xr-x 3 martinheller admin 96 Oct 19 2016 libtool drwxr-xr-x 3 martinheller staff 96 Aug 24 14:34 libunistring drwxr-xr-x 3 martinheller staff 96 Aug 27 11:37 links drwxr-xr-x 4 martinheller admin 128 Jan 5 2017 lmdb drwxr-xr-x 3 martinheller admin 96 Mar 22 14:29 nmap drwxr-xr-x 3 martinheller admin 96 Oct 19 2016 numpy drwxr-xr-x 4 martinheller admin 128 Jan 5 2017 opencv drwxr-xr-x 3 martinheller admin 96 Oct 19 2016 openexr drwxr-xr-x 6 martinheller staff 192 Aug 24 14:34 openssl drwxr-xr-x 3 martinheller admin 96 Apr 9 16:37 pcre drwxr-xr-x 3 martinheller admin 96 Apr 9 16:37 perl drwxr-xr-x 4 martinheller admin 128 Apr 9 16:37 pkg-config drwxr-xr-x 3 martinheller admin 96 Apr 9 16:37 readline drwxr-xr-x 3 martinheller admin 96 Apr 9 16:38 scons drwxr-xr-x 3 martinheller admin 96 Oct 19 2016 snappy drwxr-xr-x 3 martinheller admin 96 Apr 9 16:37 sqlite drwxr-xr-x 3 martinheller admin 96 Apr 9 16:38 subversion drwxr-xr-x 3 martinheller admin 96 Apr 9 16:37 swig drwxr-xr-x 3 martinheller admin 96 Oct 19 2016 szip drwxr-xr-x 3 martinheller admin 96 Jan 5 2017 webp drwxr-xr-x 3 martinheller staff 96 Aug 24 14:34 wget You can use list as well; ls is an alias for list. How can you find out what Homebrew supports? It’s a long list, so you probably wouldn’t want to output it in your terminal window, although you can search your current installed core and cask formula lists with brew search <name> or brew search --desc <keyword>. The core list of Homebrew packages is on the web, however, which can sometimes be more convenient, since you can scroll through and search with CMD-f: IDG A list of core Homebrew formulae, or package definitions, is available online. You can also ask Homebrew about its commands: $ brew commands Built-in commands --cache cat doctor link postinstall tap untap --cellar cleanup fetch list prune tap-info update --env command gist-logs log readall tap-pin update-report --prefix commands help migrate reinstall tap-unpin update-reset --repository config home missing search uninstall upgrade --version deps info options sh unlink uses analytics desc install outdated style unpack vendor-install cask diy leaves pin switch unpin Built-in developer commands audit create irb mirror release-notes test bottle edit linkage prof ruby tests bump-formula-pr formula man pull tap-new update-test And you can ask Homebrew to see the source code of any Homebrew formula on your machine, whether or not it is installed: $ brew cat delve class Delve < Formula desc "Debugger for the Go programming language." homepage "https://github.com/derekparker/delve" url "https://github.com/derekparker/delve/archive/v1.0.0.tar.gz" version "1.0.0" sha256 "38117c9db41db23a27a1c2e99be17d7fb73d1653de0751ee1262b460a2b26dc4" head "https://github.com/derekparker/delve.git" depends_on "go" => :build def install dlv_cert = "dlv-cert" File.open("dlv-cert.cfg", "w") do |file| file.write(%( [ req ] default_bits = 2048 # RSA key size encrypt_key = no # Protect private key default_md = sha512 # MD to use prompt = no # Prompt for DN distinguished_name = codesign_dn # DN template [ codesign_dn ] commonName = "dlv-cert" [ codesign_reqext ] keyUsage = critical,digitalSignature extendedKeyUsage = critical,codeSigning )) end find_output = `security find-certificate -Z -p -c #{dlv_cert} Library/Keychains/System.keychain` if find_output.start_with? "SHA-1 hash" ohai "#{dlv_cert} is already installed, no need to create it" else ohai "Generating #{dlv_cert}" system "openssl", "req", "-new", "-newkey", "rsa:2048", "-x509", "-days", "3650", "-nodes", "-config", "#{dlv_cert}.cfg", "-extensions", "codesign_reqext", "-batch", "-out", "#{dlv_cert}.cer", "-keyout", "#{dlv_cert}.key" ohai "[SUDO] Installing #{dlv_cert} as root" system "sudo", "security", "add-trusted-cert", "-d", "-r", "trustRoot", "-k", "/Library/Keychains/System.keychain", "#{dlv_cert}.cer" system "sudo", "security", "import", "#{dlv_cert}.key", "-A", "-k", "/Library/Keychains/System.keychain" ohai "[SUDO] Killing taskgated" system "sudo", "pkill", "-f", "/usr/libexec/taskgated" end mkdir_p buildpath/"src/github.com/derekparker" ln_sf buildpath, buildpath/"src/github.com/derekparker/delve" ENV["GOBIN"] = buildpath ENV["GOPATH"] = buildpath ENV["CERT"] = dlv_cert if head? system "make", "build" else system "make", "build", "BUILD_SHA=v#{version}" end bin.install "dlv" end def caveats; <<~EOS If you get "could not launch process: could not fork/exec", you need to try in a new terminal. When uninstalling, to remove the dlv-cert certificate, run this command: $ sudo security delete-certificate -t -c dlv-cert /Library/Keychains/System.keychain Alternatively, you may want to delete from the Keychain (with the Imported private key). EOS end test do system bin/"dlv", "version" end end You can quickly find out where any Homebrew formula is hosted and what it does: $ brew info gdbm gdbm: stable 1.18 (bottled) GNU database manager https://www.gnu.org/software/gdbm/ Not installed From: https://github.com/Homebrew/homebrew-core/blob/master/Formula/gdbm.rb ==> Options --with-libgdbm-compat Build libgdbm_compat, a compatibility layer which provides UNIX-like dbm and ndbm interfaces. For additional description, you can bring up the formula’s home page in your default browser: $ brew home gdbm You may be interested in knowing the dependencies of one or more brew formulae without seeing all the Ruby code, for example: $ brew deps mongodb gdbm openssl python@2 readline sqlite Or you may want to see the dependencies for all installed formulae: $ brew deps --installed apr: apr-util: apr openssl autoconf: automake: autoconf boost: boost-python: boost cmake: cockroach: go-delve/delve/delve: eigen: fontconfig: freetype libpng freetype: libpng gd: fontconfig freetype jpeg libpng libtiff webp gettext: gflags: glog: gflags go: gperftools: graphviz: fontconfig freetype gd jpeg libpng libtiff libtool webp hdf5: gcc gmp isl libmpc mpfr szip ilmbase: jpeg: leveldb: gperftools snappy libidn2: gettext libunistring libpng: libtiff: jpeg libtool: libunistring: links: openssl lmdb: nmap: openssl numpy: gdbm openssl python readline sqlite xz opencv: eigen ffmpeg gdbm ilmbase jpeg libpng libtiff numpy openexr openssl python python@2 readline sqlite tbb xz openexr: ilmbase openssl: pcre: perl: pkg-config: readline: scons: snappy: sqlite: readline subversion: apr apr-util openssl perl sqlite swig: pcre szip: webp: jpeg libpng wget: gettext libidn2 libunistring openssl Troubleshoot Homebrew Many utilities can be installed using Homebrew as well as with another method, such as a PKG installer or a DMG disk image. There are potential dangers when you use multiple installation methods. If you don’t pay attention, or you don’t remember what you did the last time (my hand is up for that one), you can wind up with multiple copies of a program in different locations. The first searched path that has the program is the one that will run: you may want to uninstall one of the copies. You can find out the location of the copy that will run with the which command, for example which go. You can get the full information with ls, for example ls -l `which go`. If the copy you want to uninstall was installed with Homebrew, you can delete it with brew uninstall <name>, for example brew uninstall go. Brew doesn’t delete old versions by default when you install new versions. To delete all brewed versions of one particular program, use the --force flag, for example brew uninstall --force go. To delete all old versions for all installed formulae, you can use brew cleanup. You’ll see something like this: $ brew cleanup Warning: Skipping automake: most recent version 1.16.1_1 not installed Warning: Skipping boost: most recent version 1.67.0_1 not installed Warning: Skipping boost-python: most recent version 1.67.0 not installed Warning: Skipping cmake: most recent version 3.12.1 not installed Warning: Skipping cockroach: most recent version 2.0.5 not installed Removing: /usr/local/Cellar/delve/0.12.1... (6 files, 8MB) Warning: Skipping eigen: most recent version 3.3.5 not installed Warning: Skipping fontconfig: most recent version 2.13.0 not installed Warning: Skipping freetype: most recent version 2.9.1 not installed Warning: Skipping gd: most recent version 2.2.5 not installed Warning: Skipping gflags: most recent version 2.2.1 not installed Warning: Skipping glog: most recent version 0.3.5_3 not installed Warning: Skipping gperftools: most recent version 2.7 not installed Removing: /usr/local/Cellar/graphviz/2.38.0_1... (506 files, 67.0MB) Warning: Skipping hdf5: most recent version 1.10.3 not installed Warning: Skipping ilmbase: most recent version 2.2.1 not installed Warning: Skipping jpeg: most recent version 9c not installed Warning: Skipping leveldb: most recent version 1.20_2 not installed Warning: Skipping libpng: most recent version 1.6.35 not installed Warning: Skipping libtiff: most recent version 4.0.9_4 not installed Warning: Skipping lmdb: most recent version 0.9.22 not installed Warning: Skipping numpy: most recent version 1.15.1 not installed Warning: Skipping opencv: most recent version 3.4.2 not installed Warning: Skipping openexr: most recent version 2.2.0_1 not installed Removing: /usr/local/Cellar/openssl/1.0.2j... (1,695 files, 12MB) Removing: /usr/local/Cellar/openssl/1.0.2n... (1,792 files, 12.3MB) Removing: /usr/local/Cellar/openssl/1.0.2o_1... (1,791 files, 12.3MB) Warning: Skipping perl: most recent version 5.28.0 not installed Removing: /usr/local/Cellar/pkg-config/0.29.1_2... (10 files, 627.4KB) Warning: Skipping readline: most recent version 7.0.5 not installed Warning: Skipping snappy: most recent version 1.1.7_1 not installed Warning: Skipping sqlite: most recent version 3.24.0 not installed Warning: Skipping subversion: most recent version 1.10.2 not installed Removing: /Users/martinheller/Library/Caches/Homebrew/subversion--serf-1.3.9.tar.bz2... (141.7KB) Warning: Skipping szip: most recent version 2.1.1_1 not installed Warning: Skipping webp: most recent version 1.0.0 not installed Removing: /Users/martinheller/Library/Caches/Homebrew/openssl-1.0.2n.high_sierra.bottle.tar.gz... (3.7MB) Removing: /Users/martinheller/Library/Caches/Homebrew/readline-7.0.3_1.high_sierra.bottle.tar.gz... (495.5KB) Removing: /Users/martinheller/Library/Caches/Homebrew/cockroach-1.1.3.high_sierra.bottle.tar.gz... (21MB) Removing: /Users/martinheller/Library/Caches/Homebrew/sqlite-3.23.0.high_sierra.bottle.tar.gz... (1.4MB) Removing: /Users/martinheller/Library/Caches/Homebrew/perl-5.26.1.high_sierra.bottle.1.tar.gz... (15.3MB) Removing: /Users/martinheller/Library/Caches/Homebrew/openssl-1.0.2o_1.high_sierra.bottle.tar.gz... (3.7MB) Removing: /Users/martinheller/Library/Caches/Homebrew/subversion-1.9.7.tar.bz2... (7.5MB) Removing: /Users/martinheller/Library/Caches/Homebrew/go-1.10.3.high_sierra.bottle.tar.gz... (102.6MB) Removing: /Users/martinheller/Library/Logs/Homebrew/pkg-config... (64B) Removing: /Users/martinheller/Library/Logs/Homebrew/go... (64B) Removing: /Users/martinheller/Library/Logs/Homebrew/swig... (64B) Removing: /Users/martinheller/Library/Logs/Homebrew/boost... (6 files, 19.8MB) Removing: /Users/martinheller/Library/Logs/Homebrew/apr-util... (64B) Removing: /Users/martinheller/Library/Logs/Homebrew/perl... (64B) Removing: /Users/martinheller/Library/Logs/Homebrew/scons... (64B) Removing: /Users/martinheller/Library/Logs/Homebrew/readline... (64B) Removing: /Users/martinheller/Library/Logs/Homebrew/delve... (3 files, 57.9KB) Removing: /Users/martinheller/Library/Logs/Homebrew/sqlite... (64B) Removing: /Users/martinheller/Library/Logs/Homebrew/fontconfig... (910B) Removing: /Users/martinheller/Library/Logs/Homebrew/boost-python... (64B) Removing: /Users/martinheller/Library/Logs/Homebrew/apr... (64B) Removing: /Users/martinheller/Library/Logs/Homebrew/cockroach... (64B) Removing: /Users/martinheller/Library/Logs/Homebrew/pcre... (64B) Removing: /Users/martinheller/Library/Logs/Homebrew/nmap... (64B) Removing: /Users/martinheller/Library/Logs/Homebrew/openssl... (64B) Removing: /Users/martinheller/Library/Logs/Homebrew/subversion... (17 files, 1.4MB) Removing: /Users/martinheller/Library/Logs/Homebrew/protobuf... (15 files, 1.5MB) ==> This operation has freed approximately 291MB of disk space. All of those warnings mean that I didn’t upgrade some of my installed brews. I can fix that, first by updating Homebrew to have a current catalog, and then by upgrading all brews: $ brew update Updated 2 taps (homebrew/core, homebrew/cask). ==> Updated Formulae crystal influxdb thors-serializer fortio juju youtube-dl Martins-Retina-MacBook:~ martinheller$ brew upgrade ==> Upgrading 29 outdated packages, with result: libtiff 4.0.7 -> 4.0.9_4, leveldb 1.19 -> 1.20_2, ilmbase 2.2.0 -> 2.2.1, libpng 1.6.27 -> 1.6.35, cmake 3.7.1 -> 3.12.1, freetype 2.7.1 -> 2.9.1, hdf5 1.8.18 -> 1.10.3, boost 1.63.0 -> 1.67.0_1, perl 5.26.1 -> 5.28.0, readline 7.0.3_1 -> 7.0.5, glog 0.3.4_1 -> 0.3.5_3, webp 0.5.2 -> 1.0.0, sqlite 3.23.0 -> 3.24.0, eigen 3.3.1 -> 3.3.5, numpy 1.11.2 -> 1.15.1, openexr 2.2.0 -> 2.2.0_1, fontconfig 2.12.1_2 -> 2.13.0, gflags 2.2.0 -> 2.2.1, boost-python 1.63.0 -> 1.67.0, lmdb 0.9.19 -> 0.9.22, opencv 2.4.13.2 -> 3.4.2, gperftools 2.5 -> 2.7, snappy 1.1.3 -> 1.1.7_1, gd 2.2.3_1 -> 2.2.5, cockroach 1.1.3 -> 2.0.5, jpeg 8d -> 9c, szip 2.1 -> 2.1.1_1, subversion 1.9.7_3 -> 1.10.2, automake 1.15 -> 1.16.1_1 ==> Upgrading readline ==> Downloading https://homebrew.bintray.com/bottles/readline-7.0.5.high_sierra.bottle.tar.gz ######################################################################## 100.0% ==> Pouring readline--7.0.5.high_sierra.bottle.tar.gz … By the way, the brew upgrade step was lengthy on my machine. One issue was that hdf5, which is a prerequisite for the deep learning package Keras (itself installed with pip, not brew), has a dependency of gcc, the Gnu C++ compiler. Amusingly, or annoyingly, depending on your point of view, the gcc installation on MacOS requires the Xcode Command Line Tools — in other words, you need a working Apple C++ compiler to build the Gnu C++ compiler. The process was slowed down significantly by the antivirus scan that was running, which must have been triggered by all the new downloads. I should have run the upgrade overnight or during a meal. As the late Jerry Pournelle used to say, we do stupid stuff so that you don’t have to. Once the upgrade completed, I re-ran the cleanup and freed another 900 MB of disk space. Then I checked my installation with brew doctor, which discovered a few actual problems in addition to warning about many benign conditions. I then ran brew prune to get rid of broken symlinks, and brew install with a list of missing dependencies. Homebrew bottles, casks, and taps Homebrew can install formulae two ways: by building from source code (often time-consuming) or by unpacking and installing (pouring) from a binary bottle. Bottles are gzipped tarballs of compiled binaries. Any metadata is stored in a formula’s bottle DSL and in the bottle filename (i.e. MacOS version, revision). You can see that in action in the printouts above, for example the readline installation, which pours readline--7.0.5.high_sierra.bottle.tar.gz. By default, Homebrew formulae come from the core list. If you want to use other repositories of formulae, called taps, you can add them with brew tap <user/repo>. Homebrew casks are command-line binary installers for apps that aren’t in the Mac App Store. There are currently about four thousand of them, but they aren’t in the Homebrew formulae list. Instead they can be found in the shell with brew search. For example, you can find all formulae and casks whose name contains “chrome” with this command: $ brew search chrome ==> Formulae chrome-cli chrome-export ==> Casks chrome-devtools google-chrome chrome-remote-desktop-host mkchromecast chromedriver homebrew/cask-versions/google-chrome-beta dmm-player-for-chrome homebrew/cask-versions/google-chrome-canary epichrome homebrew/cask-versions/google-chrome-dev The prefix homebrew/cask-versions/ refers to the tap for alternate versions of casks. The cask google-chrome is the current production version of Chrome; homebrew/cask-versions/google-chrome-canary is the “canary” channel version of Chrome, for early adopters and testers. You can add a tap hosted on GitHub with brew tap <user/repo>, add a Git repository hosted somewhere else using the URL, and remove a tap with brew untap <name>. If you wish, you can create your own Homebrew formulae and casks. It’s quite easy if you are familiar with Ruby and Git. The developer commands are listed several pages into the Homebrew manual man brew. Additional information, sample code, and tools can be found in the online Homebrew documentation. Related content analysis Beyond the usual suspects: 5 fresh data science tools to try today The mid-month report includes quick tips for easier Python installation, a new VS Code-like IDE just for Python and R users, and five newer data science tools you won't want to miss. By Serdar Yegulalp Jul 12, 2024 2 mins Python Programming Languages Software Development analysis Generative AI won’t fix cloud migration You’ve probably heard how generative AI will solve all cloud migration problems. It’s not that simple. Generative AI could actually make it harder and more costly. By David Linthicum Jul 12, 2024 5 mins Generative AI Artificial Intelligence Cloud Computing news HR professionals trust AI recommendations HireVue survey finds 73% of HR professionals trust AI to make candidate recommendations, while 75% of workers are opposed to AI making hiring decisions. By Paul Krill Jul 11, 2024 3 mins Technology Industry Careers how-to Safety off: Programming in Rust with `unsafe` What does it mean to write unsafe code in Rust, and what can you do (and not do) with the 'unsafe' keyword? The facts may surprise you. By Serdar Yegulalp Jul 11, 2024 8 mins Rust Programming Languages Software Development Resources Videos