Query Font Faces Safely with fc-query

fc-query opens a font file and prints every face it finds, without installing or altering anything. You will pick a single face by index, pull specific fields for a script, and learn about a documentation trap that catches out the -b option on this machine. The examples use Fontconfig 2.15.0 from the installed fontconfig package.

Allow about ten minutes. You need a readable font file and a normal shell; none of the commands here needs elevated privileges.

1. Confirm the installed command

Check the binary and package version first. A copied example against the wrong Fontconfig release fails silently far more often than it fails loudly:

$ command -v fc-query
/usr/bin/fc-query
$ fc-query --version
fontconfig version 2.15.0
$ dpkg-query -W -f='${Package} ${Version}\n' fontconfig
fontconfig 2.15.0-1.1ubuntu2

Fontconfig describes fc-query as a query over one or more font files: it prints a pattern for each face it finds. It does not install a font, rebuild the cache, or touch the file.

Checkpoint: If command -v prints nothing, install the package through your normal system administration process. Do not reach for sudo just because a font query failed.

2. Query every face in a font file

Pass a font path as the final argument. This example uses a font shipped by the local system:

$ FONT='/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf'
$ fc-query "$FONT"
Pattern has 26 elts (size 32)
\tfamily: "DejaVu Sans"(s)
\tfamilylang: "en"(s)
\tstyle: "Book"(s)
\tstylelang: "en"(s)
\tfullname: "DejaVu Sans"(s)
... 

The full pattern carries far more than this excerpt shows, including the file path, language coverage, character set and font-format details. Exact field order and the element count are output details, not an API, so do not parse the pretty-printed form in a script.

Without --index, the command queries every face in each file. That matters for collections and variable or multi-face files, where one path does not mean one result. Give several paths to compare files in one go:

$ fc-query /path/to/regular.ttf /path/to/bold.ttf

Replace both placeholders with real readable paths. A missing file is an error, and the command returns status 1 if any font face could not be opened.

3. Select one face with an index

Use -i or --index when you need one face out of each input file:

$ fc-query --index 0 "$FONT"
Pattern has 26 elts (size 32)
\tfamily: "DejaVu Sans"(s)
\tstyle: "Book"(s)
...
$ fc-query --index 1 -f '%{family}\n' "$FONT"
Can't query face 1 of font file /usr/share/fonts/truetype/dejavu/DejaVuSans.ttf
$ printf 'status: %s\n' "$?"
status: 1

4. Ask for stable fields with a format string

For automation, use -f or --format. Fontconfig pattern fields are written as %{field}; put the newline inside the format string:

$ fc-query --index 0 -f '%{family}\t%{style}\t%{file}\n' "$FONT"
DejaVu Sans	Book	/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf

That is far easier to consume than the human-readable pattern. Shell quoting protects the format string and leaves the percent signs for fc-query. Mind your delimiter: a font family can contain spaces, so splitting on spaces is unsafe.

A field-only query works for a quick check too:

$ fc-query -i 0 -f '%{family}\n%{style}\n%{index}\n' "$FONT"
DejaVu Sans
Book
0

If a field is absent, or differs between Fontconfig releases, the formatted result may not be a complete identity on its own. In a script, check the command status and validate the fields you actually require rather than treating any non-empty output as a match.

5. Use brief output only for a human glance

The installed command accepts -b and --brief to shorten the pattern display:

$ fc-query --brief "$FONT"
Pattern has 26 elts (size 32)
\tfamily: "DejaVu Sans"(s)
\tfamilylang: "en"(s)
\tstyle: "Book"(s)
...

Here is the version-sensitive trap: the installed help for Fontconfig 2.15.0 calls the long option --brief, while this machine's older local fc-query(1) page labels -b as --ignore-blanks. On this installation --ignore-blanks is rejected as an unknown option. Trust fc-query --help and the binary you are actually running over documentation that disagrees with it. The short option -b still works.

6. Handle failures without changing state

Capture the status immediately when a query runs inside a script:

if output=$(fc-query -i 0 -f '%{family}\n%{style}\n' "$FONT"); then
    printf '%s\n' "$output"
else
    status=$?
    printf 'fc-query failed with status %s\n' "$status" >&2
    exit "$status"
fi

Status 0 means the requested font data parsed successfully. Status 1 means an error occurred, or at least one face could not be opened. Neither tells you that the font suits a particular application, that it is enabled in a desktop session, or that a cache is current.

For a path problem, check readability and file type without altering anything:

$ test -r "$FONT" && echo readable
readable
$ file "$FONT"
/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf: TrueType Font data

Recovery: If you need to change installed fonts or rebuild Fontconfig's cache, stop here and follow a separate change procedure with a backup and rollback plan. fc-query itself has no undo operation because it never writes anything.

Done means