|
#!/bin/bash |
|
# |
|
# install-fonts.sh - Download and install fonts from a zip URL on Linux |
|
# |
|
# Credit to https://dev.to/pulkitsingh/install-nerd-fonts-or-any-fonts-easily-in-linux-2e3l |
|
# for inspiring this script. |
|
# |
|
# Usage: |
|
# ./install-fonts.sh [--debug|-d] [--user|-u] <font-zip-url> |
|
# ./install-fonts.sh [--debug|-d] [--user|-u] |
|
# (If no URL is given, you will be prompted to enter one.) |
|
# |
|
# Options: |
|
# -d, --debug Enable verbose debug output for troubleshooting. |
|
# -u, --user Install fonts only for the current user (no sudo/system-wide install). |
|
# -h, --help Show this help message and exit. |
|
# |
|
# Features: |
|
# - Downloads and extracts a zip file containing .ttf/.otf fonts. |
|
# - Installs each font into a subdirectory of /usr/share/fonts/truetype or /usr/share/fonts/opentype |
|
# based on the font family name (detected using fc-scan if available). |
|
# - Falls back to user font directory if root access is unavailable. |
|
# - Handles multiple font families in a single zip. |
|
# - Provides clean, user-friendly output by default. |
|
# |
|
# Soft Dependencies: |
|
# - fc-scan (from fontconfig) |
|
# This tool allows the script to detect font family names for best organization. |
|
# Without it, fonts will still be installed but may be grouped less cleanly. |
|
# |
|
# Example: |
|
# ./install-fonts.sh https://github.com/ryanoasis/nerd-fonts/releases/download/v3.4.0/0xProto.zip |
|
# ./install-fonts.sh --debug |
|
# |
|
set -e |
|
|
|
if [[ -t 1 && -z "$NO_COLOR" ]]; then |
|
RED="$(tput setaf 1 2>/dev/null || echo '\033[31m')" |
|
GREEN="$(tput setaf 2 2>/dev/null || echo '\033[32m')" |
|
YELLOW="$(tput setaf 3 2>/dev/null || echo '\033[33m')" |
|
BLUE="$(tput setaf 4 2>/dev/null || echo '\033[34m')" |
|
BOLD="$(tput bold 2>/dev/null || echo '\033[1m')" |
|
RESET="$(tput sgr0 2>/dev/null || echo '\033[0m')" |
|
else |
|
RED="" |
|
GREEN="" |
|
YELLOW="" |
|
BLUE="" |
|
BOLD="" |
|
RESET="" |
|
fi |
|
|
|
DEBUG=0 |
|
POSITIONAL=() |
|
HELP_MSG="\ninstall-fonts.sh - Download and install fonts from a zip URL on Linux\n\nCredit to https://dev.to/pulkitsingh/install-nerd-fonts-or-any-fonts-easily-in-linux-2e3l for inspiring this script.\n\nUsage:\n ./install-fonts.sh [--debug|-d] [--user|-u] <font-zip-url>\n ./install-fonts.sh [--debug|-d] [--user|-u]\n (If no URL is given, you will be prompted to enter one.)\n\nOptions:\n -d, --debug Enable verbose debug output for troubleshooting.\n -u, --user Install fonts only for the current user (no sudo/system-wide install).\n -h, --help Show this help message and exit.\n\nFeatures:\n - Downloads and extracts a zip file containing .ttf/.otf fonts.\n - Installs each font into a subdirectory of /usr/share/fonts/truetype or /usr/share/fonts/opentype\n based on the font family name (detected using fc-scan if available).\n - Falls back to user font directory if root access is unavailable.\n - Handles multiple font families in a single zip.\n - Provides clean, user-friendly output by default.\n\nSoft Dependencies:\n - fc-scan (from fontconfig)\n This tool allows the script to detect font family names for best organization.\n Without it, fonts will still be installed but may be grouped less cleanly.\n\nExample:\n ./install-fonts.sh https://github.com/ryanoasis/nerd-fonts/releases/download/v3.4.0/0xProto.zip\n ./install-fonts.sh --debug\n ./install-fonts.sh --user https://example.com/myfont.zip\n" |
|
|
|
USER_ONLY=0 |
|
while [[ $# -gt 0 ]]; do |
|
case $1 in |
|
-d | --debug) |
|
DEBUG=1 |
|
shift |
|
;; |
|
-u | --user) |
|
USER_ONLY=1 |
|
shift |
|
;; |
|
-h | --help) |
|
echo -e "$HELP_MSG" |
|
exit 0 |
|
;; |
|
*) |
|
POSITIONAL+=("$1") |
|
shift |
|
;; |
|
esac |
|
done |
|
set -- "${POSITIONAL[@]}" |
|
|
|
function debug_msg() { |
|
if [[ $DEBUG -eq 1 ]]; then |
|
echo "[DEBUG] $1" |
|
fi |
|
} |
|
|
|
if ! command -v fc-scan >/dev/null 2>&1; then |
|
echo -e "${NOTICE} For best font organization, please install: fc-scan${RESET}" |
|
echo -e " This tool allows the script to detect font family names and organize fonts into the correct directories." |
|
echo -e " The script will still work, but fonts may be grouped less cleanly." |
|
echo |
|
echo -e " To install fc-scan: sudo apt install fontconfig" |
|
echo |
|
fi |
|
|
|
if [ -z "$1" ]; then |
|
read -rp "Enter the URL to a font zip file: " FONT_URL |
|
else |
|
FONT_URL="$1" |
|
fi |
|
|
|
if [ -z "$FONT_URL" ]; then |
|
echo -e "${ERROR}No URL provided. Exiting.${RESET}" |
|
exit 1 |
|
fi |
|
|
|
TEMP_DIR=$(mktemp -d) |
|
debug_msg "Created temp dir: $TEMP_DIR" |
|
trap 'rm -rf "$TEMP_DIR"' EXIT |
|
|
|
echo -e "${BLUE}Downloading font zip from $FONT_URL...${RESET}" |
|
wget -q -O "$TEMP_DIR/font.zip" "$FONT_URL" |
|
debug_msg "Downloaded to $TEMP_DIR/font.zip" |
|
|
|
echo -e "${BLUE}Extracting font archive...${RESET}" |
|
unzip -q "$TEMP_DIR/font.zip" -d "$TEMP_DIR" |
|
debug_msg "Unzipped to $TEMP_DIR" |
|
|
|
mapfile -t FONT_FILES < <(find "$TEMP_DIR" -type f \( -iname '*.ttf' -o -iname '*.otf' \)) |
|
|
|
if [[ ${#FONT_FILES[@]} -eq 0 ]]; then |
|
echo -e "${RED}Error: No .ttf or .otf font files found in the archive.${RESET}" |
|
exit 2 |
|
fi |
|
|
|
declare -A INSTALLED_SUMMARY |
|
if [[ $DEBUG -eq 1 ]]; then |
|
echo "Installing fonts..." |
|
fi |
|
for FONT_PATH in "${FONT_FILES[@]}"; do |
|
EXT="${FONT_PATH##*.}" |
|
FAMILY="" |
|
if command -v fc-scan >/dev/null 2>&1; then |
|
FAMILY=$(fc-scan --format='%{family[0]}\n' "$FONT_PATH" | head -n 1) |
|
debug_msg "fc-scan family for $FONT_PATH: $FAMILY" |
|
fi |
|
if [[ -z "$FAMILY" ]]; then |
|
FAMILY=$(basename "$FONT_PATH" | sed -E 's/[-_]*$//; s/\..*$//') |
|
debug_msg "Fallback family for $FONT_PATH: $FAMILY" |
|
fi |
|
FAMILY_DIR=$(echo "$FAMILY" | tr '[:upper:]' '[:lower:]' | sed -E 's/[[:space:]]+/-/g') |
|
if [[ "$EXT" == "ttf" ]]; then |
|
SYS_DIR="/usr/share/fonts/truetype/$FAMILY_DIR" |
|
USER_DIR="$HOME/.local/share/fonts/truetype/$FAMILY_DIR" |
|
else |
|
SYS_DIR="/usr/share/fonts/opentype/$FAMILY_DIR" |
|
USER_DIR="$HOME/.local/share/fonts/opentype/$FAMILY_DIR" |
|
fi |
|
|
|
if [[ $USER_ONLY -eq 1 ]]; then |
|
mkdir -p "$USER_DIR" |
|
cp "$FONT_PATH" "$USER_DIR/" |
|
debug_msg "Installed $(basename "$FONT_PATH") to $USER_DIR (user fonts)" |
|
INSTALLED_SUMMARY["$FAMILY"]+="$(basename "$FONT_PATH") (user)"$'\n' |
|
else |
|
if sudo mkdir -p "$SYS_DIR" && sudo cp "$FONT_PATH" "$SYS_DIR/"; then |
|
debug_msg "Installed $(basename "$FONT_PATH") to $SYS_DIR" |
|
INSTALLED_SUMMARY["$FAMILY"]+="$(basename "$FONT_PATH") (system)"$'\n' |
|
else |
|
mkdir -p "$USER_DIR" |
|
cp "$FONT_PATH" "$USER_DIR/" |
|
debug_msg "Installed $(basename "$FONT_PATH") to $USER_DIR (user fonts)" |
|
INSTALLED_SUMMARY["$FAMILY"]+="$(basename "$FONT_PATH") (user)"$'\n' |
|
fi |
|
fi |
|
done |
|
|
|
if [[ $DEBUG -eq 0 ]]; then |
|
echo -e "${GREEN}Installed fonts:${RESET}" |
|
for FAMILY in "${!INSTALLED_SUMMARY[@]}"; do |
|
printf " ${BOLD}%s${RESET}:\n%s" "$FAMILY" "${INSTALLED_SUMMARY[$FAMILY]}" |
|
done |
|
fi |
|
|
|
if [[ $USER_ONLY -eq 1 ]]; then |
|
if [[ $DEBUG -eq 1 ]]; then |
|
fc-cache -f -v "$HOME/.local/share/fonts" |
|
else |
|
fc-cache -f "$HOME/.local/share/fonts" >/dev/null 2>&1 |
|
echo -e "${GREEN}Fonts installed successfully!${RESET}" |
|
fi |
|
else |
|
if [[ $DEBUG -eq 1 ]]; then |
|
sudo fc-cache -f -v |
|
else |
|
sudo fc-cache -f >/dev/null 2>&1 |
|
echo -e "${GREEN}Fonts installed successfully!${RESET}" |
|
fi |
|
fi |