Last active
March 17, 2025 17:34
-
-
Save ardnew/7ce3141faaeaa4e1219f201b43bd0baa to your computer and use it in GitHub Desktop.
Extract font files installed by Adobe Creative Cloud
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# This script extracts the locally-cached font files installed by | |
# Adobe Creative Cloud. | |
# | |
# The extracted fonts can then be used in other applications. | |
# | |
# See --help|-h for usage information. | |
usage() { | |
cat <<__usage__ | |
USAGE | |
${0##*/} INCACHE OUTDIR | |
ARGUMENTS | |
• INCACHE — Path to the Adobe CoreSync font cache. | |
(default "~/Library/Application Support/Adobe/CoreSync/plugins/livetype") | |
• OUTDIR — Output directory for extracted font files. | |
(default "~/Library/Fonts/Adobe") | |
NOTES | |
The contents of the INCACHE directory are hidden directories, | |
and each of their contents are hidden font files with obfuscated | |
names. The structure of INCACHE is similar to (macOS): | |
~/Library/Application Support/Adobe/CoreSync/plugins/livetype | |
├── .r | |
│ ├── .1022.otf | |
│ ├── .1023.otf | |
│ ├── .1024.otf | |
│ ├── .1025.otf | |
│ └── .1026.otf | |
└── .w | |
├── .26498.otf | |
├── .26499.otf | |
├── .26503.otf | |
├── .28123.otf | |
└── .28124.otf | |
(...) | |
After extraction, font files will be grouped into directories | |
per font family, with a separate font file for each style. | |
The structure of OUTDIR will be similar to (macOS): | |
~/Library/Fonts/Adobe | |
├── AdaptiveMono OT | |
│ ├── AdaptiveMonoOT-Bold.otf | |
│ ├── AdaptiveMonoOT-BoldOblique.otf | |
│ ├── AdaptiveMonoOT-Oblique.otf | |
│ └── AdaptiveMonoOT-Regular.otf | |
└── Aglet Mono | |
├── AgletMono-Black.otf | |
├── AgletMono-BlackItalic.otf | |
├── AgletMono-Bold.otf | |
├── AgletMono-BoldItalic.otf | |
├── AgletMono-ExtraLight.otf | |
├── AgletMono-ExtraLightItalic.otf | |
├── AgletMono-Italic.otf | |
├── AgletMono-Light.otf | |
├── AgletMono-LightItalic.otf | |
├── AgletMono-Regular.otf | |
├── AgletMono-Semibold.otf | |
├── AgletMono-SemiboldItalic.otf | |
├── AgletMono-Ultra.otf | |
└── AgletMono-UltraItalic.otf | |
(...) | |
__usage__ | |
exit 0 | |
} | |
[[ "${*/#--[hH]/-h}" != -h* ]] || usage | |
path=${1:-"${HOME}/Library/Application Support/Adobe/CoreSync/plugins/livetype"} | |
dest=${2:-"${HOME}/Library/Fonts/Adobe"} | |
if [[ ! -d "${path}" ]]; then | |
echo "error: invalid path to Adobe fonts" >&2 | |
exit 1 | |
fi | |
print() { | |
local -a fmt=( ) | |
local -a cmd=( ) | |
while [[ ${#} -gt 0 && "${1}" != "--" ]]; do | |
fmt+=( "${1}" ) | |
shift | |
done | |
[[ ${#} -lt 2 || "${1}" != "--" ]] || | |
cmd=( "${@:2}" ) | |
if [[ ${#cmd[@]} -eq 0 ]]; then | |
printf -- "${fmt[@]}" >&2 | |
return | |
fi | |
local def="running command: ${cmd[@]}" | |
if gum=$( type -P gum ); then | |
"${gum}" spin \ | |
--title="$( printf -- "${fmt[@]:-${def}}" )" \ | |
--spinner="minidot" \ | |
--show-output \ | |
-- "${cmd[@]}" | |
else { | |
printf -- "${fmt[@]:-${def}}" | |
"${cmd[@]}" | |
echo | |
} >&2 | |
fi | |
} | |
copy() { | |
local -r file=${1} | |
local -r dest=${2} | |
while read -re dat; do | |
[[ -n "${dat}" ]] || continue | |
local p=$( cut -f1 <<< "${dat}" ) | |
local f=$( cut -f2 <<< "${dat}" ) | |
local s=$( cut -f3 <<< "${dat}" ) | |
local o=$( cut -f4 <<< "${dat}" ) | |
[[ "{${p}}" != "{}" ]] || p=${file} | |
[[ "{${f}}" != "{}" ]] || continue # skip if no family name | |
[[ "{${o}}" == "{}" ]] || s=${o} | |
[[ "{${s}}" != "{}" ]] || s=${f} | |
local name="${f}/${s}.${p##*.}" | |
mkdir -p "${dest}/${f}" && | |
cp -v "${p}" "${dest}/${name}" || | |
continue | |
done < <( fc-scan --format='%{file}\t%{family[0]}\t%{fullname}\t%{postscriptname}\n' "${file}" ) | |
} | |
while read -re file; do | |
copy "${file}" "${dest}" | |
done < <( print 'scanning fonts: %s' "${path}" -- find "${path}" -type f ) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment