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.
fontconfig package.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.
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.
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
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.
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.
fc-list reports fonts known to Fontconfig, not every file somewhere below /usr/share/fonts or your home directory. If a new font is absent, check that it sits in a Fontconfig search path and that the database has been refreshed.fc-match, not the first line from fc-list.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.
-f.--quiet makes an unmatched query return status 1.