Inspect Installed Fonts with fc-list Without Guesswork

Stop guessing whether a font is installed: fc-list shows exactly which fonts Fontconfig can use. You will narrow the list by family or language, print useful properties and produce stable output for a script. The examples were checked with Fontconfig 2.15.0 and take about ten minutes.

1. Confirm the installed command

Check which executable your shell will run, then record its version. This helps when a guide or script was written for a different Fontconfig release:

$ command -v fc-list
/usr/bin/fc-list
$ fc-list --version
fontconfig version 2.15.0

Your version may differ. Keep it beside your troubleshooting notes, because the available options and the ordering of results belong to the installed command and font configuration, not to this article.

Checkpoint: if command -v prints nothing, install Fontconfig through your normal distribution package manager. Do not copy a font directory into a system location to solve a missing command.

2. List every visible font face

Run fc-list without arguments for the quickest inventory:

$ fc-list | head -5
/usr/share/fonts/truetype/lato/Lato-Medium.ttf: Lato,Lato Medium:style=Medium,Regular
/usr/share/fonts/truetype/lato/Lato-SemiboldItalic.ttf: Lato,Lato Semibold:style=Semibold Italic,Italic
/usr/share/fonts/truetype/dejavu/DejaVuSerif-Bold.ttf: DejaVu Serif:style=Bold
/usr/share/fonts/opentype/urw-base35/URWBookman-LightItalic.otf: URW Bookman:style=Light Italic
/usr/share/fonts/opentype/urw-base35/URWBookman-Light.otf: URW Bookman:style=Light

Each line is a file path followed by Fontconfig's family and style fields. One family can appear on several lines, because it may have multiple faces, styles or family aliases. The order is no guide to a preferred font.

Use less for an interactive list rather than flooding the terminal:

$ fc-list | less

Press q to leave less.

Tip: piping to head is only a preview. It does not mean Fontconfig found five fonts.

3. Filter by a Fontconfig pattern

Put a pattern in quotes so the shell passes it as one argument. This example selects faces whose family is Lato:

$ fc-list ':family=Lato' family style file | head -5
/usr/share/fonts/truetype/lato/Lato-Medium.ttf: Lato,Lato Medium:style=Medium,Regular
/usr/share/fonts/truetype/lato/Lato-SemiboldItalic.ttf: Lato,Lato Semibold:style=Semibold Italic,Italic
/usr/share/fonts/truetype/lato/Lato-LightItalic.ttf: Lato,Lato Light:style=Light Italic,Italic
/usr/share/fonts/truetype/lato/Lato-Italic.ttf: Lato:style=Italic
/usr/share/fonts/truetype/lato/Lato-MediumItalic.ttf: Lato,Lato Medium:style=Medium Italic,Italic

The empty pattern : matches all fonts. After the pattern, property names choose what is printed: family prints the family, file prints the font file. Omit them and you get the usual family and style view, unless verbose output is requested.

To find faces that cover a language, use the language property from the manual's example:

$ fc-list ':lang=hi' | head -5

An empty result is meaningful: this machine may have no installed face covering Hindi. It is not evidence that the command failed. Check the exit status when a script needs to tell an empty result from a successful match:

$ fc-list ':family=__no_such_family__' >/tmp/fc-list-empty.txt
$ printf 'exit status: %s\n' "$?"
exit status: 0

Without --quiet, an unmatched query still exits successfully on this installed command. With --quiet, normal output is suppressed and the exit status is 1 when no font matches:

$ fc-list --quiet ':family=__no_such_family__'
$ printf 'exit status: %s\n' "$?"
exit status: 1

4. Print fields in a script-friendly format

Use -f or --format when another command needs predictable columns. Fontconfig format strings use property names in braces; \t and \n make tabs and line breaks:

$ fc-list ':family=Lato' -f '%{family}\t%{style}\t%{file}\n' | head -5
Lato,Lato Hairline	Hairline,Regular	/usr/share/fonts/truetype/lato/Lato-Hairline.ttf
Lato,Lato Heavy	Heavy,Regular	/usr/share/fonts/truetype/lato/Lato-Heavy.ttf
Lato,Lato Medium	Medium,Regular	/usr/share/fonts/truetype/lato/Lato-Medium.ttf
Lato,Lato Light	Light Italic,Italic	/usr/share/fonts/truetype/lato/Lato-LightItalic.ttf
Lato	Italic	/usr/share/fonts/truetype/lato/Lato-Italic.ttf

The rows depend on the fonts installed and the current Fontconfig database. Do not parse the default colon-separated display if you need reliable field boundaries. Use a format string, and quote it so the shell does not expand the braces or interpret the tab escapes.

Tip: a missing property can produce an empty field. Handle that as data; do not guess a replacement file name.

5. Inspect a complete match when a field is unclear

Add --verbose to print the complete font pattern for each match. It helps when a family has aliases, several languages or different file formats:

$ fc-list --verbose ':family=Lato' | head -16
Pattern has 28 elts (size 32)
	family: "Lato"(s)
	familylang: "en"(s)
	style: "Hairline"(s)
	stylelang: "en"(s)
	fullname: "Lato Hairline"(s)
	fullnamelang: "en"(s)
	slant: 0(i)(s)
	weight: 0(f)(s)
	width: 100(f)(s)
	foundry: "tyPL"(s)
	file: "/usr/share/fonts/truetype/lato/Lato-Hairline.ttf"(s)

Verbose output is for inspection, not a stable interface. Fields can be added or reordered between versions, and the values reflect the local font files.

6. Avoid the common traps

Warning: refreshing a system-wide font database can affect other applications. Use your distribution's documented font installation process, and do not run a cache command blindly as root.

Keep output files in a temporary location when experimenting. The examples write only to /tmp/fc-list-empty.txt; remove that harmless file when finished:

$ rm -- /tmp/fc-list-empty.txt

This removal is optional and irreversible for that file. None of the font files or Fontconfig configuration is changed by the listing commands.

Done means