Script to install latest hugo release on macos and ubuntu

Made a script to install the latest hugo release (non-extended version) on macOS. It works on Ubuntu as well, just replace occurrences of macOS with Linux.

Edit: This assumes $HOME/bin/ is already on your PATH

Edit 2: It now does all work in /tmp/, then moves the hugo binary to /usr/local/bin/, so this script will likely need need to be run with sudo

# Change to temporary directory
pushd /tmp/

# Get JSON response of latest releases, find the one we want, 
# pretty-up the URL, then download it
curl -s \
| grep "browser_download_url.*hugo_[^extended].*_macOS-64bit\.tar\.gz" \
| cut -d ":" -f 2,3 \
| tr -d \" \
| wget -qi -

# Unzip hugo binary
tarball="$(find . -name "*macOS-64bit.tar.gz")"
tar -xzf $tarball

# Give hugo binary executable permissions
chmod +x hugo

# Move hugo binary to a location that is already on your PATH
mv hugo /usr/local/bin/

# Go back to previous directory

# Display hugo binary location and version
location="$(which hugo)"
echo "Hugo binary location: $location"
version="$(hugo version)"
echo "Hugo binary version: $version"

My inspiration:


Also note:


Nice. It’s like he took the Gradle Wrapper concept and applied it to Hugo

Also, mostly because I need to explain things to myself lol, did a small write-up:

1 Like

I do it this way, with a zsh function (I’m using macOS):

Yours is more agnostic I think @zwbetz, but I just really like jq.


Nice. Btw, I’m digging your .zshrc file

1 Like

beware, probably a lot of detritus in there! :blush:

Here’s my improved version. Checks if update is needed first. Avoids having to remember to preface with sudo. Checking local architecture and downloading the correct tarball is next improvement.


CUR_VERSION="$(hugo version | cut -d'v' -f2 | cut -c 3-5)"
NEW_VERSION="$(curl -s | grep tag_name | cut -d'.' -f2 | cut -d'"' -f1)"
echo "Current Version: $CUR_VERSION => New Version: $NEW_VERSION"

if [ "$NEW_VERSION" -ne "$CUR_VERSION" ]; then

  echo "Installing version $NEW_VERSION"

  pushd /tmp/

  curl -s \
  | grep "browser_download_url.*hugo_[^extended].*_Linux-64bit\.tar\.gz" \
  | cut -d ":" -f 2,3 \
  | tr -d \" \
  | wget -qi -

  tarball="$(find . -name "*Linux-64bit.tar.gz" 2>/dev/null)"
  tar -xzf $tarball

  chmod +x hugo

  sudo mv hugo /usr/local/bin/


  location="$(which hugo)"
  echo "Hugo binary location: $location"

  version="$(hugo version)"
  echo "New Hugo binary version installed!: $version"

  echo Latest version already installed

@dkebler – Just took it for a spin on macOS, nice improvements :+1:

Ok here is my “super improved” version as a downloadable link
(latest update 8:26pst Nov 9,2018)
I’ll make any corrections/improvements to the copy at this link.

Easiest way to use it is download to ~/bin or another directory in your path. Do a chmod +x and then you’ll be able to run it from anywhere. Then create a daily cron job and bob’s your uncle.

Will only work on generic linux including ubuntu/debian as it only downloads those tarballs.

  • Will determine if you are trying to install on an arm32, arm64, or amd64 machine and download the correct tarball.
  • Does some better error checking, aborts if there is nothing to update
  • You can set the default install directory in the script and/or install to an alternate directory from command line.
  • Uses sudo only if need be.
  • will use github user and token variables you can set in your enviroment or in script because as I discovered if you do too many anonymous curls to the github API it locks you out

Fair warning I did do some good testing/debugging but my effort was maybe 1/2 hour. Find anything amiss why then do share your corrections.

1 Like

Link not working (at least for me):

Concur, not working for me either.

sorry that’s apparently a private thread and discourse won’t let me duplicate it
See above or below post where I fixed it with a direct downloadable link

There was request to post source here. It’s below but will likely become outdated as changes are made so to see/download the latest use this link

# Version 0.1.0  8:26 PST, Nov 9, 2018
# see
# if you have run into github api anonymous access limits then add user and token here or in environment

# Single optional argument is directory in which to install hugo
BIN_PATH="$(which hugo)"
declare -A ARCHES
ARCHES=( ["arm64"]="ARM64" ["aarch64"]="ARM64"  ["x86_64"]="64bit" ["arm32"]="ARM"  ["armhf"]="ARM" )

if [ -z "${ARCHES[$ARCH]}" ]; then
  echo  Your machine kernel architecture $ARCH is not supported by this script, aborting
  exit 1

INSTALLED="$(hugo version 2>/dev/null | cut -d'v' -f2 | cut -c 3-5)"
             | grep tag_name \
             | cut -d'.' -f2 | cut -d'"' -f1)"

echo "Hugo:  Current Version: $CUR_VERSION => New Version: $NEW_VERSION"

if [ -z "$NEW_VERSION" ]; then
  echo  Unable to retrieve new version number - Likely you have reached github anonymous limit
  echo  set environment variable `$GITHUB_USER` and `$GITHUB_TOKEN` and try again
  exit 1

if ! [ $NEW_VERSION = $CUR_VERSION ]; then

  echo "Installing version $NEW_VERSION"
  echo "This machine's architecture is $ARCH"
  echo "Downloading Tarball Linux-${ARCHES[$ARCH]}"

  pushd /tmp/ > /dev/null

  | grep "browser_download_url.*hugo_[^extended].*_Linux-${ARCHES[$ARCH]}\.tar\.gz" \
  | cut -d ":" -f 2,3 \
  | tr -d \" \
  | wget --user=-u $GITHUB_USER --password=$GITHUB_TOKEN -qi -

  TARBALL="$(find . -name "*Linux-${ARCHES[$ARCH]}.tar.gz" 2>/dev/null)"
  echo Expanding Tarball
  tar -xzf $TARBALL

  chmod +x hugo

if [ -w $BIN_DIR ]; then
  echo "Installing hugo to $BIN_DIR"
  mv hugo -f $BIN_DIR
    echo "sudo Installing hugo to $BIN_DIR"
    sudo mv -f hugo $BIN_DIR

  popd > /dev/null

  BIN_PATH="$(which hugo)"
  if [ -z "$BIN_PATH" ]; then
  printf "WARNING: Installed Hugo Binary in $BIN_DIR is not in your environment path\nPATH=$PATH\n"
  if [ "$BIN_DIR/hugo" != "$BIN_PATH" ]; then
  echo "WARNING: Just installed Hugo binary, $BIN_DIR , conflicts with existing Hugo in $BIN_PATH"
  echo "add $BIN_DIR to path and delete $BIN_PATH"
  echo "--- Confirmation ---"
  printf "New Hugo binary version in $BIN_DIR is\n $($BIN_DIR/hugo version)\n"

  echo Latest version already installed in $BIN_PATH

Just for any getting here. To be clear the “improved” script not only installs hugo but will update an existing install. One script to rule all but updates on windows

Hi @dkebler, been happily using this script on Ubuntu but have been playing with Manjaro Linux recently I found the script doesn’t work out of the box, it can’t find the kernel architecture and aborts. Seems that ‘arch’ command doesn’t work on arch based distros =D

Got it working by using uname -m instead, but not sure how portable that is. So comment out original line and use uname like so:

ARCH=$(uname -m)

@dkebler It also seems this script will replace a manually installed hugo-extended with the normal hugo.

Here’s an example run (edited to remove an apostrophe that messes up syntax colouring on here):

hugo version
Hugo Static Site Generator v0.54.0-B1A82C61A/extended linux/amd64 BuildDate: 2019-02-01T10:04:38Z

Hugo:  Current Version: 54. => New Version: 54
Installing version 54
This machines architecture is x86_64
Downloading Tarball Linux-64bit
Expanding Tarball
tar: LICENSE: Cannot open: File exists
tar: Cannot open: File exists
tar: Exiting with failure status due to previous errors
sudo Installing hugo to /usr/local/bin
[sudo] password for adrian: 
--- Confirmation ---
New Hugo binary version in /usr/local/bin is
 Hugo Static Site Generator v0.54.0-B1A82C61 linux/amd64 BuildDate: 2019-02-01T09:40:34Z

hugo version-
Hugo Static Site Generator v0.54.0-B1A82C61 linux/amd64 BuildDate: 2019-02-01T09:40:34Z

I’ve updated my script and made some improvements. Will install regular hugo by default but using e one can install extended version and with c option can have both side by side i.e run hugo and hugoe

here is the gist