Skip to content

Instantly share code, notes, and snippets.

@smoser
Last active July 14, 2025 14:14
Show Gist options
  • Save smoser/13d05fe92a2e4fae1010421e759715ec to your computer and use it in GitHub Desktop.
Save smoser/13d05fe92a2e4fae1010421e759715ec to your computer and use it in GitHub Desktop.
nerd-font installer

nerd-font installer

Install nerd-fonts from https://www.nerdfonts.com/font-downloads. Credit to this gist and comments there for inspiration

Edit 'myfonts' function to install more fonts.

Usage

$ ../nerd-font  -h
nerd-font subcmd [options]

    dl font[@version] [output]

       download the font to output. 
       output defaults to <font>.zip
       version defaults to 'latest'

    install font[@version]

       download font and install it to /home/smoser/.local/share/fonts
       if font is a local file named *.zip, then just install it.
   
    install-all

       call install on all fonts in:

         CascadiaMono
         FiraCode
         Hack
         JetBrainsMono
         UbuntuMono

#!/bin/sh
# shellcheck disable=SC2015,SC3043
# adapted from https://gist.github.com/matthewjberger/7dd7e079f282f8138a9dc3b045ebefa0
TEMP_D=""
FONTS_D="${FONTS_D:-${HOME}/.local/share/fonts}"
#FONTS_D="/usr/share/fonts"
myfonts() {
# BitstreamVeraSansMono
# CascadiaCode
# CodeNewRoman
# DroidSansMono
# FiraCode
# FiraMono
# Go-Mono
# Hack
# Hermit
# JetBrainsMono
# Meslo
# Noto
# Overpass
# ProggyClean
# RobotoMono
# SourceCodePro
# SpaceMono
# Ubuntu
# UbuntuMono
cat <<EOF
CascadiaMono
FiraCode
Hack
JetBrainsMono
UbuntuMono
EOF
}
fail() { stderr "FATAL:" "$@"; exit 1; }
stderr() { echo "$@" 1>&2; }
Usage() {
# shellcheck disable=SC2046
cat <<EOF
${0##*/} subcmd [options]
dl font[@version] [output]
download the font to output.
output defaults to <font>.zip
version defaults to 'latest'
install font[@version]
download font and install it to ${FONTS_D}
if font is a local file named *.zip, then just install it.
install-all
call install on all fonts listed in 'myfonts' function:
$(printf " %s\n" $(myfonts))
EOF
}
dlfont() {
local font="$1" out="$2" version="latest" zip="" tmpf="" url=""
case "$font" in
*@*) font="${1%@*}"; version="${1#*@}";;
esac
if [ "$version" = "latest" ]; then
url="https://github.com/ryanoasis/nerd-fonts/releases/$version/download/$font.zip"
else
url="https://github.com/ryanoasis/nerd-fonts/releases/download/v${version#v}/$font.zip"
fi
zip="$font.zip"
[ -z "$out" ] && out="$zip"
tmpf="$out.tmp.$$"
wget -O "$tmpf" "$url" &&
mv "$tmpf" "$out" || {
rm -f "$tmpf"
stderr "failed to download $font@$version"
return 1
}
return 0
}
cleanup() {
[ -n "$TEMP_D" ] || return 0
rm -Rf "$TEMP_D"
}
install() {
local font="" zip=""
mkdir -p "$FONTS_D" ||
{ stderr "could not create font dir $FONTS_D"; return 1; }
TEMP_D=$(mktemp -d "${TMPDIR:-/tmp}/${0##*/}.XXXXXX") || return 1
trap cleanup EXIT
[ $# -ne 0 ] || { stderr "install got zero things to install"; return 1; }
for font in "$@"; do
case "$font" in
*.zip)
if [ ! -f "$font" ]; then
stderr "font '$font' is not a local file"
return 1
fi
zip="$font"
;;
*) dlfont "$font" "${TEMP_D}/${font##*/}.zip" ||
{ stderr "failed downloading $font"; return 1; }
zip="${TEMP_D}/${font##*/}.zip"
;;
esac
unzip -o "$zip" -d "$FONTS_D" ||
{ stderr "unzip installation of $zip failed [$?] to $FONTS_D"; return 1; }
done
find "$FONTS_D" -name 'Windows Compatible' -delete ||
{ stderr "failed removing windows compatible files"; return 1; }
fc-cache -fv ||
{ stderr "fc-cache -fv failed"; return 1; }
return 0
}
main() {
local name="$1"
[ $# -eq 0 ] && { Usage 1>&2; exit 1; }
shift
case "$name" in
-h|--help) Usage; exit 0;;
install-all|install)
if [ "$name" = "install" ]; then
[ $# -ge 1 ] || fail "install expects a font. got none"
elif [ $# -ne 0 ]; then
fail "install-all got a font. expects none"
else
# shellcheck disable=SC2046
set -- $(myfonts)
fi
install "$@" || fail "$name failed"
;;
dl)
if [ $# -ne 1 ] && [ $# -ne 2 ]; then
fail "dl got $# args, expect 1 or 2"
fi
dlfont "$@" || fail "download of $1 ${2:+to $2 }failed"
;;
*) Usage 1>&2; exit 1;;
esac
}
main "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment