Skip to content

What the page does not say

Level: 201 · for anyone who has read the manual and still guessed

One line: iconv accepts //TRANSLIT and //IGNORE, and not one of the 17,264 man pages on this Mac mentions either — documentation fails silently in both directions, so the only reliable question is the one you ask the program.

A flag that works and is written down nowhere

iconv(1) on macOS documents five options: -c, -f, -l, -s, -t. That is the whole page. It says nothing about the conversion-name suffixes, which are the feature people actually need, because the default behaviour when a character will not fit is to stop.

Measured 2026-09-07 — macOS 26.6, citrus iconv. Input is 'naïve café €' as UTF-8: 6e61 c3af 7665 2063 6166 c3a9 20e2 82ac.
$ iconv -f UTF-8 -t ASCII            < in.txt
iconv: iconv(): Illegal byte sequence

$ iconv -f UTF-8 -t ASCII//TRANSLIT  < in.txt
na"ive caf'e EUR

$ iconv -f UTF-8 -t ASCII//IGNORE    < in.txt
nave caf

Three behaviours, two of them reachable only if you already knew the syntax. And the sweep is unambiguous about where that syntax is documented:

find /usr/share/man ... -type f | sort > /tmp/manfiles.txt   # 17,264 files
xargs < /tmp/manfiles.txt grep -l -- '//TRANSLIT'            # (no output)

Note also that //TRANSLIT here is not accent-stripping. ï becomes "i and é becomes 'e — the quote-before-letter convention of the old mnemonic tables — while becomes EUR. Anyone who assumed "transliterate to ASCII" meant naive cafe has a second surprise waiting, and the man page cannot warn them about a flag it does not have.

The failure runs the other way too

multibyte(3)'s SEE ALSO names mklocale(1), and mkcsmapper and mkesdb are named by its neighbours. None of the three is installed:

for p in mklocale mkcsmapper mkesdb; do man -w "$p" >/dev/null 2>&1 || echo "$p: no such page"; done

So the tree under-describes what exists and over-describes what does not, in the same section, on the same day. Neither failure announces itself. A cross-reference to a missing page is at least visible the moment you follow it; an undocumented flag is invisible forever, because there is nothing to follow.

So ask the program

The habit that replaces trust is small: try it, and read the exit status. For a shell tool that is three lines.

probe() { printf 'a' | iconv -f UTF-8 -t "$1" >/dev/null 2>&1 && echo "$1: yes" || echo "$1: no"; }
probe 'ASCII//TRANSLIT'
probe 'ASCII//NONSENSE'

For a library it is better than that, because the registry can be asked rather than probed. Python's manual prints a table of about a hundred codecs; codecs.lookup() answers to several hundred names, because it normalises punctuation and case before it searches and because the alias table is far larger than any page that lists it.

Verified output of what_the_page_does_not_say_py.py — regenerated by tools/run_examples.py, never hand-typed.

1. ONE CODEC, MANY SPELLINGS -- lookup() NORMALISES BEFORE IT SEARCHES
   codecs.lookup('utf-8'  ).name -> 'utf-8'
   codecs.lookup('utf8'   ).name -> 'utf-8'
   codecs.lookup('utf_8'  ).name -> 'utf-8'
   codecs.lookup('UTF-8'  ).name -> 'utf-8'
   codecs.lookup('U8'     ).name -> 'utf-8'
   codecs.lookup('utf 8'  ).name -> 'utf-8'

   Six spellings, one codec.  Punctuation and case are folded away, so
   a name absent from the documented table may still be a live alias.

2. NAMES THE TUTORIALS DO NOT PRINT, ASKED DIRECTLY
   latin1      -> iso8859-1
   l1          -> iso8859-1
   cp819       -> iso8859-1
   iso8859-1   -> iso8859-1
   utf-8-sig   -> utf-8-sig
   punycode    -> punycode
   idna        -> idna
   undefined   -> undefined
   mbcs        -> LookupError: unknown encoding
   cp65001     -> utf-8
   utf-9       -> LookupError: unknown encoding

   'l1' and 'cp819' are Latin-1 under names no page here has ever used.
   'mbcs' is real, and Windows-only -- a documented codec that is a
   LookupError on this machine.  So the answer is a fact about the
   interpreter you are running, not about the language.

3. THE PROBE, AS A FUNCTION YOU CAN KEEP
   asked for 12 names
   present:  utf-8, shift_jis, koi8-r, cp1250, big5, euc-kr, utf-7, iso2022_jp, tis-620, kz1048
   absent:   utf-2, ebcdic

   Three lines, and no documentation was consulted.  Write the same
   probe for any tool: try the flag, read the exit status, and believe
   the machine over the page -- in both directions.

Section 2 has the two results worth keeping. l1 and cp819 are Latin-1 under names no tutorial prints — the same one-encoding-many-names problem iconv -l shows with 873 aliases over 215 codesets. And mbcs is a documented codec that raises LookupError here, because it is Windows-only: the manual is accurate about the language and wrong about the interpreter you are running.

That is the general shape. Documentation describes a class of machines; you are on one machine.

When the page is all you have

Probing settles what a tool accepts. It does not settle what a tool means, and there the page is still the only source — which is why the answer is not "skip the docs" but "read the docs and then check". Three cases where checking is cheap and worth it every time:

Question How to settle it in one line
Does this flag exist here? run it against trivial input and read $?
Is this name an alias? iconv -l \| grep -i NAME, or codecs.lookup(name).name
Does this page still describe the tool? the date in the bottom margin, and a page has a date

If you are coming from Python or ABAP

Python is the good case: dir(), help(), codecs.lookup() and inspect.signature() mean the implementation answers for itself, and the answer is about your interpreter. Prefer it to the docs whenever the two are cheap to compare — and note that this cuts the other way for behaviour under error, where help() is silent and only the docs explain what errors='surrogateescape' is for.

ABAP has the same split. SE24 and SE11 show you what actually exists in this system — the class, its methods, whether that interface was implemented in this release — where SAP Help Portal describes a release you may not be on. For encodings specifically, the system is the only authority on which code pages are installed; a Note listing a code page is not evidence that your system has it. (Not machine-checked — CI cannot run ABAP.)

Try it

  1. iconv -f UTF-8 -t ASCII//TRANSLIT on a file with an accent in it. Then man iconv and search for TRANSLIT.
  2. python3 -c "import codecs; print(codecs.lookup('l1').name)".
  3. Take the last flag you looked up in a manual and probe it instead. Time both.
  4. Follow every SEE ALSO on man 3 multibyte. Count how many resolve.

Practice

Ask the program. iconv accepts //TRANSLIT and //IGNORE, and no man page on this library's Mac mentions either. Run printf 'caf\303\251\n' | iconv -f UTF-8 -t ASCII//TRANSLIT on your own machine and record both the output and the exit status.

Then compare with the measured results for the other platform: the same command produces different text and a different status. Say what that means for "use //TRANSLIT" as advice, and give the three questions that actually settle something about a tool.

Answers

Verified output of what_the_page_does_not_say_kata_py.py — regenerated by tools/run_examples.py, never hand-typed.

THE CLAIM TO TEST
   iconv accepts //TRANSLIT and //IGNORE as suffixes on the target
   encoding, and not one man page on this library's Mac mentions
   either -- 17,264 pages searched, 2026-09-07.

SO ASK THE PROGRAM. MEASURED 2026-09-07, INPUT 'café' AS UTF-8:

                        macOS 26 (BSD iconv)        Ubuntu 24.04 (glibc)
   -t ASCII             refuses, exit 1             refuses, exit 1
   -t ASCII//TRANSLIT   caf'e      exit 1           caf?       exit 0
   -t ASCII//IGNORE     caf        exit 1           caf        exit 1

   Read the middle row twice. The flag exists on both, it is documented
   on neither, it produces DIFFERENT TEXT on the two systems -- an
   approximation on one and a question mark on the other -- and it
   disagrees about whether that counts as success.

   So 'use //TRANSLIT' is not portable advice, and no page would have
   told you: the feature is undocumented in both places, and the
   difference is undocumented everywhere.

DOCUMENTATION FAILS SILENTLY IN BOTH DIRECTIONS
   It can OMIT a feature that exists -- the case above.
   It can DESCRIBE a feature that no longer behaves as stated: a man
   page carries the date of whoever last edited it, not the date of the
   binary sitting beside it.
   Neither failure announces itself. Both look like a complete page.

THE THREE QUESTIONS THAT ACTUALLY SETTLE SOMETHING
   1. What does it DO?        run it on a two-line input and read the
      output AND the exit status -- the middle row above differs in both
   2. WHICH program is it?    --version, and `which -a`; there are two
      of most of these tools and you have one
   3. WHEN was this written?  the date at the foot of the page and the
      RFC number it cites are evidence about the DOCUMENT, never about
      the binary

THE RECIPE, WHICH IS THE ACTUAL ANSWER
   printf 'caf\303\251\n' | iconv -f UTF-8 -t ASCII//TRANSLIT; echo $?
   Two lines, thirty seconds, and it answers for YOUR machine -- which
   is the only machine the answer was ever true for.

   That is not cynicism about documentation. It is this library's own
   rule pointed at its sources: a claim is worth what the program that
   produced it is worth, and a page is a claim nobody re-ran.

See also