tr(1) on Solnix vs Linux and the BSDs

On Solnix, tr is the illumos tr at /usr/bin/tr, and its man page describes a System V-style range syntax, [c-c], where Linux and the BSDs use c-c. The other big difference is that /usr/bin/tr does not list -C and leaves the result unspecified when string2 is shorter than string1, whereas Linux and the BSDs pad string2 with its last character.

What Solnix runs

A default Solnix system runs /usr/bin/tr (illumos). /usr/xpg4/bin/tr and /usr/xpg6/bin/tr are also shipped. The xpg4 synopsis has no -C and documents ranges as c-c. The xpg6 synopsis accepts [-c | -C]. /usr/ucb/tr is shipped too, but the bundle does not describe it. The -C option appears in the OPTIONS section, but only the xpg6 synopsis lists it, not the /usr/bin/tr synopsis.

Differences

Compared withTopicWhat differs
all fourrange syntaxThe Solnix page documents the range construct as [c-c] for /usr/bin/tr and as c-c for /usr/xpg4/bin/tr. Linux, FreeBSD, OpenBSD and NetBSD document c-c (Linux: CHAR1-CHAR2). The Solnix text shown does not say how /usr/bin/tr treats a plain a-z.
Source: Solnix tr(1) OPERANDS, /usr/xpg4/bin/tr c-c and /usr/bin/tr [c-c]; Linux tr(1) CHAR1-CHAR2; FreeBSD/OpenBSD/NetBSD tr(1) c-c
all fourstring2 shorter than string1Solnix says the result is unspecified when string2 is shorter than string1. Linux, FreeBSD, OpenBSD and NetBSD all repeat the last character of string2 to fill the gap. Scripts that rely on this padding are not safe on Solnix.
Source: Solnix tr(1) OPTIONS (When the -d option is not specified); Linux tr(1) DESCRIPTION (ARRAY2 is extended); FreeBSD/OpenBSD/NetBSD tr(1) DESCRIPTION
all four-C and -c on /usr/bin/trThe Solnix /usr/bin/tr synopsis is [-cds], without -C. -C is listed in OPTIONS and in the xpg6 synopsis. Linux, FreeBSD and OpenBSD synopses accept -C. NetBSD has only -c.
Source: Solnix tr(1) SYNOPSIS, OPTIONS -C; Linux tr(1) -c, -C; FreeBSD/OpenBSD tr(1) SYNOPSIS; NetBSD tr(1) SYNOPSIS
Linux, FreeBSD, OpenBSD-c versus -C meaningSolnix -c complements by binary value (ascending). Solnix -C complements by character set and LC_COLLATE order. FreeBSD draws a similar distinction. On Linux and OpenBSD, -c and -C are the same, and OpenBSD says this is because tr is not locale-aware.
Source: Solnix tr(1) OPTIONS -c, -C; FreeBSD tr(1) -C, -c; Linux tr(1) -c, -C, --complement; OpenBSD tr(1) -c, STANDARDS
LinuxGNU-only options and syntaxLinux tr (GNU coreutils) has -t/--truncate-set1, long options, --help and --version, the [CHAR*] and [CHAR*REPEAT] forms, and a \\ escape. The Solnix text shown has none of these. Do not use them in Solnix scripts.
Source: Linux tr(1) -t, --truncate-set1, --help, --version, [CHAR*REPEAT], \\; Solnix tr(1) SYNOPSIS, OPERANDS
FreeBSD-u unbuffered outputFreeBSD tr has -u to guarantee unbuffered output. The Solnix synopses have no -u.
Source: FreeBSD tr(1) -u; Solnix tr(1) SYNOPSIS
FreeBSD, OpenBSD, NetBSDrepeat construct [#*n]FreeBSD, OpenBSD and NetBSD document [#*n] for string2. OpenBSD and NetBSD tell portable scripts to use it instead of relying on last-character padding. The Solnix text in the bundle is trimmed and shows no equivalent.
Source: FreeBSD/OpenBSD/NetBSD tr(1) [#*n]; OpenBSD tr(1) STANDARDS; NetBSD tr(1) STANDARDS
all four-d with -sOn Solnix, using -d and -s together requires both string1 (to delete) and string2 (to squeeze), and the same string cannot serve both. FreeBSD, OpenBSD and NetBSD synopses show tr -ds string1 string2 as well. The Solnix page states the same-string restriction explicitly.
Source: Solnix tr(1) OPTIONS (When the -d option is specified); FreeBSD/OpenBSD/NetBSD tr(1) SYNOPSIS
all fourcharacter classes in string2On Solnix, string2 accepts only [:lower:] and [:upper:] (for case conversion), unless both -d and -s are given. The Linux, FreeBSD, OpenBSD and NetBSD texts shown do not state this restriction.
Source: Solnix tr(1) OPERANDS [:class:]; Linux/FreeBSD/OpenBSD/NetBSD tr(1) [:class:]
FreeBSDextra class namesFreeBSD lists the classes ideogram, phonogram, rune and special. The Solnix list is alnum, alpha, blank, cntrl, digit, graph, lower, print, punct, space, upper and xdigit, plus any class defined in LC_CTYPE.
Source: FreeBSD tr(1) [:class:]; Solnix tr(1) OPERANDS [:class:]
FreeBSD, OpenBSD, NetBSDNUL bytes and syntax checkingOpenBSD and NetBSD state that tr handles NUL bytes and rejects illegal syntax, for example -c or -s with one string and no other operands. The Solnix text shown says nothing about NULs; its /usr/bin/tr synopsis allows no operands or just string1.
Source: OpenBSD tr(1) STANDARDS; NetBSD tr(1) COMPATIBILITY; Solnix tr(1) SYNOPSIS

Standards

  • POSIX: tr is a POSIX.1-2024 utility.
  • OpenBSD: Compliant with the IEEE Std 1003.1-2008 (“POSIX.1”) specification, except that -C behaves the same as -c since tr is not locale-aware.
  • NetBSD: Expected to be IEEE Std 1003.2 (“POSIX.2”) compatible.
  • Solnix: The visible Solnix text does not include a standards section. It ships separate /usr/xpg4/bin/tr and /usr/xpg6/bin/tr variants.

Writing portable scripts

  • Do not rely on string2 being padded when it is shorter than string1. Make string2 the same length as string1. Where string2 must be extended, use [#*n] only after testing, since the Solnix text shown does not document it.
  • For case conversion, use tr '[:lower:]' '[:upper:]', which all five pages document. Avoid ranges such as a-z in scripts that must also run on Solnix /usr/bin/tr, which documents [c-c].

Every difference here is taken from the manual pages linked above: Solnix's published page, Linux (man-pages and the GNU and util-linux manuals), FreeBSD, OpenBSD and NetBSD. Each row names its source. Where a manual is silent, this page is too. Compiled 2026-10-26. Found a mistake? Mail hackers@lists.solnix.io.