Extract Selected Glyphs from a Linux Console Font with splitfont
splitfont is a tiny, old kbd utility that pulls individual glyphs out of a raw Linux console font, one file per character. It comes from kbd 2.6.4-2ubuntu2 here. Give it about fifteen minutes.
The route
Jump straight to the step you need, or tick off Done means at the end.
- You need: the kbd package, and a font in the exact format this old tool expects: no PSF header, exactly 256 characters.
- It will not: load a font, touch the console, or need
sudo. Work on a temporary copy.
1. Check the installed command
Confirm the binary and its short usage message:
$ command -v splitfont
/usr/bin/splitfont
$ dpkg-query -W -f='${Package} ${Version}\n' kbd
kbd 2.6.4-2ubuntu2
$ splitfont
call: splitfont fontfile 17,23-30,...
The syntax is splitfont FONTFILE RANGE..., where a range is a comma-separated list of decimal character numbers and inclusive ranges, such as 17,23-30. The manual describes the expected input as an ISO-type font with 256 characters and no PSF header.
Checkpoint
If the file you have is a .psf font, do not hand it over directly. The PSF header makes it the wrong input format for this tool. Only strip it to a headerless working copy once you understand the source format and glyph size.
2. Prepare a safe working copy
Never experiment on the only copy of a font. This example takes the 4,096 glyph bytes from an installed 8 by 16, 256-character PSF font, after its 32-byte PSF2 header. It is a test fixture for splitfont, not a general PSF conversion recipe:
$ workdir=$(mktemp -d /tmp/splitfont.XXXXXX)
$ dd if=/usr/share/consolefonts/UbuntuMono-R-8x16.psf \
of="$workdir/font.raw" bs=1 skip=32 count=4096 status=none
$ stat -c '%n: %s bytes' "$workdir/font.raw"
/tmp/splitfont.XXXXXX/font.raw: 4096 bytes
A 256-character font at 16 bytes per glyph comes to 4,096 bytes. Your font may use a different glyph height, so calculate the real raw size rather than copying these numbers blindly. Already have a headerless font? Copy it to a temporary directory under a new name and work there instead.
Skip sudo for this step unless the source is unreadable to your account. If you genuinely need elevated access, copy the source to a directory you own first, then run splitfont on that copy.
3. Extract individual characters
Pick character numbers and run the command from the directory holding the working copy:
$ cd "$workdir"
$ splitfont font.raw 65,66-67
$ printf 'status: %s\n' "$?"
status: 0
$ ls -l font.raw.41 font.raw.42 font.raw.43
-rw-r--r-- 1 you you 16 ... font.raw.41
-rw-r--r-- 1 you you 16 ... font.raw.42
-rw-r--r-- 1 you you 16 ... font.raw.43
- Decimal in, hex out. 65, 66 and 67 are the requested decimal character numbers, but the generated suffixes are hexadecimal:
.41,.42,.43. - One glyph per file. Each output is exactly the font's glyph height, 16 bytes here.
Ranges are inclusive, so 23-30 asks for eight consecutive characters. Keep the range list explicit in scripts, and quote the font path if it contains spaces:
$ splitfont '/path/to/raw font' 32,48-57,65-90
$ printf 'status: %s\n' "$?"
status: 0
4. Verify the result and the source
Check the extracted files have the right size, and that the source came through unaltered:
$ sha256sum font.raw > before.sha256
$ splitfont font.raw 65
$ sha256sum -c before.sha256
font.raw: OK
$ stat -c '%n: %s bytes' font.raw.41
font.raw.41: 16 bytes
splitfont writes extracted files beside the input and, in this test, does not touch the input itself. Treat that as an observed property of this installed build, not a licence to skip backups when the font actually matters. If an output file with the same name already exists, stop and inspect it first; the command may silently overwrite it.
To compare a glyph against its position in the raw source, use a byte offset of the character number times the glyph height. For character 65 in this 16-byte font:
$ dd if=font.raw bs=16 skip=65 count=1 status=none | cmp - font.raw.41
$ printf 'compare status: %s\n' "$?"
compare status: 0
Checkpoint
Status 0 means the extracted file matches the corresponding 16-byte slice exactly. That is a byte check, not a visual preview.
5. Handle the common input errors
Seeing file unexpectedly large means the input is not the required 256-glyph, headerless size. Check its size and format before touching anything:
$ file /path/to/font
$ stat -c '%s bytes' /path/to/font
The installed program also rejects a file whose size is not a multiple of 256, but that check will not spot a PSF header for you, and a file that passes it can still hold the wrong data. Use a known font format and a deliberate conversion step, not a guess.
A mistyped range returns a non-zero status and a bad-argument message. Do not infer the output name from a decimal suffix: the actual names are hexadecimal. If the command cannot open the file, fix the path or read permission rather than reaching for root to paper over the mistake.
Done means
- Package confirmed. kbd and
splitfontare installed and on yourPATH. - Format matched. You used a headerless, 256-character working font.
- Ranges explicit. Characters were requested with decimal values or inclusive ranges.
- Output located. One glyph file per request, named with hexadecimal suffixes.
- Result verified. Output size checked and at least one glyph compared against its source slice.
- Source and console untouched. The original font stayed safe and the active console font never changed.