Skip to content

Instantly share code, notes, and snippets.

@ardnew
Last active March 17, 2025 17:34
Show Gist options
  • Save ardnew/7ce3141faaeaa4e1219f201b43bd0baa to your computer and use it in GitHub Desktop.
Save ardnew/7ce3141faaeaa4e1219f201b43bd0baa to your computer and use it in GitHub Desktop.
Extract font files installed by Adobe Creative Cloud
#!/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