Skip to content
GrubsicPublic

About

No description, website, or topics provided.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Repository files navigation

winfonts

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.

Quick start

Make the launcher executable after downloading or cloning:

chmod +x winfonts

Open the guided menu:

./winfonts

The 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 wizard

For 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

Commands

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 --help

Misspelled commands receive a suggestion when a close match exists.

Interactive mode

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.

Supported sources

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.*.dat files;
  • individual .ttf, .otf, .ttc, .otc files 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.json

Temporary 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.

Preview before installing

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.json

The 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.

Office media

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-only

Useful 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-only usually finds shared Office fonts much faster.
  • --office-all-resources includes all language resources; automatic mode uses available resources if no neutral stream exists. --office-language TAG selects that language instead of the automatic neutral scan.
  • --office-arch accepts auto, x64, x86, or all; auto prefers x64 when present and otherwise selects x86.
  • --office-language TAG may 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-media

Nested 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 media

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.iso

To select another edition:

./winfonts images Windows.iso
./winfonts install Windows.iso --image 6

wimlib-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.

Inspecting managed fonts

List every managed file:

./winfonts list

Example:

[ok] Aptos Bold -> /home/me/.local/share/fonts/winfonts/office/Aptos-Bold.ttf
Total: 1

Show only status totals:

./winfonts status

Both commands support JSON for scripts:

./winfonts list --json
./winfonts status --json

Possible 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.

Repairing the manifest

Preview every applicable repair:

./winfonts repair --dry-run

Apply only explicitly selected changes:

./winfonts repair --drop-missing --compact
./winfonts repair --drop-modified --drop-symlink --compact
./winfonts repair --recover-pending

Normal 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.

Uninstalling

Always preview first:

./winfonts uninstall --dry-run

Then remove the managed files:

./winfonts uninstall

For a custom manifest:

./winfonts uninstall --manifest /path/to/manifest.jsonl

Uninstall verifies every file hash. Missing, modified, unsafe, or unexpected files are not deleted; their records remain in the manifest for inspection.

Paths and custom destinations

Show defaults:

./winfonts paths

Default 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.img

Override 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-all

The 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-existing skips identical metadata and older versions.
  • prefer-newer installs only new faces or newer revisions.
  • install-source installs the supplied source side-by-side unless its exact file content already exists at the selected target. The old name prefer-source remains as a deprecated alias.
  • keep-all preserves 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.

Dependencies

Check the current machine:

./winfonts doctor

Core requirements:

  • Python 3;
  • Fontconfig tools: fc-scan, fc-list, and fc-cache;
  • the bundled office_font_carver.py.

Source-specific tools:

  • mount and umount when opening ISO/IMG files directly;
  • 7z, 7zz, or 7za for 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-imagex as the preferred Windows WIM/ESD reader; 7-Zip can extract fonts when it is missing. Listing editions with images still requires wimlib;
  • cabextract and msiextract as 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.

Mount permissions and sudo

Some distributions restrict loop mounting to root:

sudo ./winfonts scan Office.img --office-x-none-only
sudo ./winfonts install Windows.iso

If 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/office

If 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

Safety model

  • 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-all never 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-sha256 verifies 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-pending removes 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 fsync calls for stronger Linux crash durability.

Licensing and redistribution

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.

Exit codes

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

Development

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

About

No description, website, or topics provided.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages