Step-by-step tutorial · Media validation
winfonts extracts Microsoft fonts from Windows and Office media on Linux. It
validates every font, chooses the newest internal font revision across all inputs, installs readable filenames, records
what it changed, and can safely undo the installation later.
It does not download or redistribute fonts. You provide the Windows or Office media and remain responsible for complying with its license.
Make the launcher executable after downloading or cloning:
chmod +x winfontsOpen the guided menu:
./winfontsThe menu can scan, install, list, verify, and uninstall fonts without requiring you to remember command-line options. It is also available explicitly:
./winfonts interactive
./winfonts menu
./winfonts wizardFor command-line use:
./winfonts doctor
./winfonts scan /path/to/offline-installers --temp-dir /path/to/scratch --report preview.json
./winfonts scan /path/to/Office.img --office-x-none-only
./winfonts install /path/to/Office.img --office-x-none-only
./winfonts install /path/to/Windows.iso --source-sha256 EXPECTED_SHA256
./winfonts list
./winfonts status
./winfonts repair --dry-run
./winfonts uninstall --dry-run
./winfonts uninstall| Command | Purpose |
|---|---|
interactive |
Open the guided menu. This is automatic when no command is given in a terminal. |
doctor |
Check core and source-specific dependencies. |
scan SOURCE... |
Preview extraction and installation without writing font files. |
install SOURCE... |
Extract, validate, deduplicate, and install fonts. |
images SOURCE |
List Windows editions contained in WIM/ESD media. |
list |
List font files managed by winfonts and verify each one. |
status |
Summarize valid, missing, modified, or unsafe managed files. |
repair |
Safely forget invalid records or compact an inconsistent manifest. |
paths [SOURCE...] |
Show default paths and source-specific destinations. |
uninstall |
Remove files safely using the installation manifest. |
help [COMMAND] |
Show general or command-specific help. |
version |
Show the installed version. |
Useful aliases:
add install
preview, dry-run scan
list-images, editions images
installed list
verify status
rollback, remove uninstall
fix-manifest repair
check doctor
where paths
menu, wizard interactive
Detailed help is available in either style:
./winfonts help install
./winfonts install --helpMisspelled commands receive a suggestion when a close match exists.
Run ./winfonts in a terminal and choose an action from the menu.
The menu is printed once when opened. Completed or cancelled actions return to
the action prompt without clearing the screen or printing the menu again. Enter
m to show the menu again, h for help, or q to quit. Progress bars update only
their own line while work is running.
The wizard:
- accepts paths containing spaces;
- supports multiple sources in one run;
- accepts quoted paths, expands
~, and checks paths before continuing; - accepts folders containing multiple offline installers;
- detects each source automatically, including folders mixing Windows, Office and archives;
- automatically uses neutral Office resources when available, with full scans as an override;
- exposes destination, manifest, architecture, language, and image-index options only when requested;
- asks for confirmation before installing;
- always previews an uninstall before asking for confirmation.
Regular non-interactive commands retain their existing behavior, making them safe to use in scripts.
One command may receive one or more sources:
- Windows ISO or IMG files;
- mounted Windows setup media;
install.wim,install.esd, or a directory containing either;- an installed Windows partition containing
Windows/Fonts; - Office Click-to-Run IMG files or mounted media;
- legacy Office media containing CAB or MSI payloads;
- standalone CAB, MSI, MSP and MSM files, including embedded CAB streams;
- ZIP, 7z, RAR, TAR and compressed archives supported by the installed 7-Zip;
- self-extracting EXE installers that 7-Zip can read (installers are never executed);
- standalone Office
stream.*.datfiles; - individual
.ttf,.otf,.ttc,.otcfiles or directories of fonts; - folders of offline media: supported files are discovered recursively, with repeated paths removed.
MSI/CAB fonts with an appended component identifier or no font extension are recognized by their binary signature and then validated with Fontconfig. An EXE extension alone does not guarantee an extractable installer. MSP support extracts complete embedded fonts; binary delta patches requiring a base installation are not applied. Split WIM sets are not supported.
All candidates from all sources are deduplicated together:
./winfonts scan Windows.iso Office.img --office-x-none-only
./winfonts install Office1.img Office2.img --office-x-none-only
./winfonts scan /path/to/media-folder --temp-dir /path/to/scratch --report decisions.jsonTemporary extraction defaults to $XDG_CACHE_HOME/winfonts/tmp (normally
~/.cache/winfonts/tmp), avoiding RAM-backed /tmp for large media. An explicit
--temp-dir must already exist. Use a disk with enough free space for the largest
expanded source plus the collected fonts; Windows 11 media may require more than
8 GiB. Sources are unpacked one at a time and their media temporary files are
released before the next source. Identical Click-to-Run payloads in the same run
reuse extracted candidates after SHA-256 verification. No persistent font cache
or dependency on a particular sample folder is created.
Windows, Office, and loose-font sources use separate destination folders unless
--dest overrides them.
scan makes the same extraction and duplicate decisions as install, but does
not write font files or update the manifest:
./winfonts scan /path/to/Windows.iso
./winfonts scan /path/to/Office.img --office-x-none-only
./winfonts install /path/to/source --dry-run
./winfonts scan /path/to/source --report decisions.jsonThe optional JSON report records each source, font metadata, internal revision, SHA-256, decision and target. It is a decision plan, not proof of a completed installation. Reports must use a new filename; existing files are not overwritten.
Example:
Selection: 12 candidates | 1 selected
Skipped: 8 duplicates | 3 older versions | 0 invalid
Would install: 1
Skipped/invalid: 11
The default display is compact: an updating progress bar in interactive terminals
and a small number of plain status lines when redirected. Counts and percentages
are shown when measurable; blocking extraction steps use an activity bar. Warnings
remain visible. Use --no-progress to disable animation, --verbose to show every
selected font and extraction diagnostic, or --report decisions.json for the full
decision plan. --verbose also disables animation so diagnostic output stays readable.
Readable source filenames are preserved. If Windows or Office exposes an opaque
resource identifier, winfonts derives a filename from the font's internal
family and style metadata. A short hash is added only when two different files
would otherwise use the same filename.
Modern Click-to-Run media automatically scans language-neutral resources when available. You can also request this explicitly:
./winfonts scan Office.img --office-x-none-only
./winfonts install Office.img --office-x-none-onlyUseful Office options:
./winfonts scan Office.img --office-arch x64
./winfonts scan Office.img --office-arch all
./winfonts scan Office.img --office-all-resources
./winfonts scan Office.img --office-language en-us--office-x-none-onlyusually finds shared Office fonts much faster.--office-all-resourcesincludes all language resources; automatic mode uses available resources if no neutral stream exists.--office-language TAGselects that language instead of the automatic neutral scan.--office-archacceptsauto,x64,x86, orall;autoprefers x64 when present and otherwise selects x86.--office-language TAGmay be repeated to include language-specific streams.
Legacy Office media is handled separately. If a source contains recognizable
Office CAB or MSI payloads, winfonts uses 7-Zip, with cabextract and/or msiextract
as alternatives when 7-Zip is unavailable,
without executing Windows installers:
./winfonts scan /path/to/legacy-office-media
./winfonts install /path/to/legacy-office-mediaNested CAB/MSI payloads are processed recursively with content deduplication and a safety limit. Individual extraction failures are reported with the payload path and tool output while other payloads continue.
Loose font files found in modern Office media are copied before opaque Click-to-Run streams are carved.
Windows setup media defaults to image index 1. Most Windows fonts are shared
between editions, so this is normally enough:
./winfonts scan Windows.iso
./winfonts install Windows.isoTo select another edition:
./winfonts images Windows.iso
./winfonts install Windows.iso --image 6wimlib-imagex is required for Windows ISO, WIM, and ESD sources but is not
required for Office or loose-font directories.
To verify official media before extraction and retain the verified digest in the manifest:
EXPECTED_SHA256="replace-with-the-64-hex-digit-published-checksum"
./winfonts install Windows.iso --source-sha256 "$EXPECTED_SHA256"For multiple media files, repeat the option and identify each source:
./winfonts install Windows.iso Office.img \
--source-sha256 "Windows.iso=$WINDOWS_SHA256" \
--source-sha256 "Office.img=$OFFICE_SHA256"Only regular-file sources can be hashed; mounted directories cannot.
List every managed file:
./winfonts listExample:
[ok] Aptos Bold -> /home/me/.local/share/fonts/winfonts/office/Aptos-Bold.ttf
Total: 1
Show only status totals:
./winfonts statusBoth commands support JSON for scripts:
./winfonts list --json
./winfonts status --jsonPossible verification states include ok, missing, modified, symlink,
and malformed.
Installation requires a clean manifest. If status reports any invalid state,
install stops before extraction or copying so a missing file cannot be
reinstalled over a stale record.
Preview every applicable repair:
./winfonts repair --dry-runApply only explicitly selected changes:
./winfonts repair --drop-missing --compact
./winfonts repair --drop-modified --drop-symlink --compact
./winfonts repair --recover-pendingNormal repair options modify only the manifest and never alter or follow a font
file or symlink. --recover-pending may remove a regular file
listed in an interrupted-install journal when its SHA-256 still matches the
planned copy. Already committed files and changed files are preserved.
--compact resolves duplicate destination records by keeping the newest record
whose file still verifies, then removes transaction records no longer
referenced by a managed font.
Always preview first:
./winfonts uninstall --dry-runThen remove the managed files:
./winfonts uninstallFor a custom manifest:
./winfonts uninstall --manifest /path/to/manifest.jsonlUninstall verifies every file hash. Missing, modified, unsafe, or unexpected files are not deleted; their records remain in the manifest for inspection.
Show defaults:
./winfonts pathsDefault per-user locations:
Windows fonts: ~/.local/share/fonts/winfonts/windows
Office fonts: ~/.local/share/fonts/winfonts/office
Loose fonts: ~/.local/share/fonts/winfonts/loose
Manifest: ~/.local/state/winfonts/manifest.jsonl
Classify sources and show where each would install:
./winfonts paths Windows.iso Office.imgOverride the destination or manifest:
./winfonts install Office.img \
--office-x-none-only \
--dest "$HOME/.local/share/fonts/my-office-fonts" \
--manifest "$HOME/.local/state/winfonts-office.jsonl"Common short options:
-n, --dry-run Preview only.
-o, --dest DIR Override the font destination.
-m, --manifest PATH Override the manifest path.
-i, --image N Override the Windows WIM/ESD image index.
Duplicate policy options:
./winfonts install SOURCE --duplicate-policy skip-existing
./winfonts install SOURCE --duplicate-policy prefer-newer
./winfonts install SOURCE --duplicate-policy install-source
./winfonts install SOURCE --duplicate-policy keep-allThe default is prefer-newer. All sources are compared before choosing files,
so putting an older installer first does not select its older font. Versions are
the fonts' internal numeric revisions (fontversion, a 16.16 fixed-point value),
not file timestamps, installer years, filenames or filesystem order. Equal
revisions use a deterministic SHA-256 tie-break; a missing revision is not evidence
that a font is newer. Localized names and TTC index changes do not create a new
identity when the PostScript name matches. Styles and variable fonts remain distinct.
skip-existingskips identical metadata and older versions.prefer-newerinstalls only new faces or newer revisions.install-sourceinstalls the supplied source side-by-side unless its exact file content already exists at the selected target. The old nameprefer-sourceremains as a deprecated alias.keep-allpreserves exact duplicates too, always chooses new filenames, and never overwrites a pre-existing file.
Collections (TTC/OTC) are kept intact. A collection fully superseded by newer faces
is skipped; one containing a unique face is preserved even if other faces overlap
older versions. The report identifies such overlap (collection-retains-older-faces
or partially-duplicated-collection). Files already installed by the OS or other
tools are not removed. Upgrading an existing installation adds newer files safely;
it does not delete previously installed older files. To rebuild a WinFonts-managed
set without previous versions, preview its uninstall, uninstall it, then install
all desired sources together. uninstall applies to the entire selected manifest.
Check the current machine:
./winfonts doctorCore requirements:
- Python 3;
- Fontconfig tools:
fc-scan,fc-list, andfc-cache; - the bundled
office_font_carver.py.
Source-specific tools:
mountandumountwhen opening ISO/IMG files directly;7z,7zz, or7zafor archives/installers and as a non-root ISO/IMG reader; format support depends on the installed build (a full 7-Zip build is recommended);wimlib-imagexas the preferred Windows WIM/ESD reader; 7-Zip can extract fonts when it is missing. Listing editions withimagesstill requires wimlib;cabextractandmsiextractas alternatives for legacy Office media when 7-Zip is unavailable.
Missing source-specific tools are reported as optional because Office media, mounted directories, and loose-font folders may still work.
Some distributions restrict loop mounting to root:
sudo ./winfonts scan Office.img --office-x-none-only
sudo ./winfonts install Windows.isoIf 7-Zip is installed, winfonts automatically falls back to extracting an
ISO/IMG into a temporary directory when a read-only loop mount is unavailable.
It lists the image first, checks free space, and extracts only the relevant
Windows WIM/ESD, Office streams, legacy payloads, or loose fonts when the media
layout is recognizable. Unknown layouts use a checked full-image fallback.
When run through sudo, winfonts targets the original SUDO_USER home rather
than /root.
You may also mount media yourself:
sudo mount -o loop,ro Office.img /mnt/office
./winfonts scan /mnt/office --office-x-none-only
sudo umount /mnt/officeIf the project was copied from Windows and ./winfonts reports sh\r, ensure
Git respects the included .gitattributes, or run:
git add --renormalize winfonts
git checkout -- winfonts
chmod +x winfonts- Default installs are per-user, not system-wide.
- Sources are opened read-only.
- Symlinked source candidates and unsafe archive paths are rejected.
- Fonts are validated with Fontconfig before and after copying.
- Copies use a verified temporary file and an atomic create-only hard link, so a target created after planning is never overwritten.
- Content hashes prevent accidental duplicate installation.
keep-allnever reuses or overwrites an existing pathname.- Planned filenames are reserved to prevent same-run overwrites.
- Every installed file is recorded in a JSON Lines manifest.
--source-sha256verifies media before extraction and records its provenance.- Uninstall verifies hashes before deleting anything.
- A lock prevents install, uninstall, and status operations from racing.
- Destination-specific locks also serialize operations that use different manifests but write to the same font directory.
- Failed transactions roll back files already copied by that transaction.
- Before copying, installs persist a pending journal containing every planned
destination and SHA-256. After an abrupt process or power failure,
repair --recover-pendingremoves only matching uncommitted files. - A failed manifest write always returns an error after rollback, even when the aborted transaction can be recorded successfully.
- Duplicate-only installs do not add empty transactions to the manifest.
- Manifest renames and font-directory mutations are followed by directory
fsynccalls for stronger Linux crash durability.
Use media obtained from Microsoft or your own legitimately licensed installation. Keep extracted proprietary fonts local to the licensed machine. Do not commit them to Git, publish them in packages or containers, place them on shared servers, or convert them to another font format as a redistribution workaround. Font embedding in documents is a separate right controlled by each font's OpenType embedding flags.
Microsoft's font redistribution FAQ specifically states that Segoe UI Variable is not licensed for use outside Microsoft products or on non-Windows platforms. For document compatibility without proprietary binaries, consider metric-compatible Liberation fonts. This project is an extraction tool, not legal advice.
| Code | Meaning |
|---|---|
0 |
Success |
2 |
Invalid command, option, source type, or missing core dependency |
3 |
Required source or manifest not found |
4 |
No fonts found |
5 |
Nothing new was installed because candidates were duplicates |
6 |
Partial operation or incomplete transaction |
7 |
Verification found modified or unsafe files |
8 |
Another operation holds the lock |
10 |
Filesystem or I/O failure |
130 |
Interrupted |
Run the test suite on Linux:
python3 -m unittest discover -s tests -v
python3 -m py_compile winfonts_engine.py winfonts_ui.py office_font_carver.py