TAC(1) General Commands Manual TAC(1)

tacconcatenate reversed files

tac [-rb] [-s eparator] [file]…

Read each file (standard input stream if "-", the default), split it on the separator expression, matching from the end, and write it back out to the standard output stream, starting with the final match.

, --separator=sep
Separate by sep instead of a single newline. An empty separator matches nothing (and the invocation is equivalent to cat).
, --regex
Treat separator as basic regular expression. An empty separator is refused.
, --before
Write separator before its line.

if a file couldn't be opened or read.

cat(1), rev(1)

Expects to map or read each file into main memory.

tail appeared in Version 7 AT&T UNIX, allowing up to one file, with an undocumented-in-the-manual -r mode, largely equivalent to present-day tac, but allowing the usual lbc specifiers for line, -byte block, and byte limits (with a global 4-kilobyte buffer for -r (and relative-to-EOF addressing it implied)).

3BSD removes -r.

4.2BSD re-adds -r, with broken interactions with bc specifiers.

4.3BSD bumps the buffer size to 32 kilobytes and fixes the c interaction to not affect the result.

4.4BSD fixes bc (-bc) interactions with r (-r), allows multiple files (with the usual tail headers between them), and removes buffer limitations.

AT&T System III UNIX removes -r.

AT&T System V Release 4 UNIX re-adds it, only allowing line limits.

As such, tac originates, fully formed, from GNU textutils at or before version 1.11, and persists in GNU coreutils; this implementation is compatible with the GNU system.

NetBSD 9.0 provides tac as a link to tail, implying -r with headings suppressed, quoting compatibility with the GNU system.

April 24, 2023 voreutils pre-v0.0.0-latest