Subject: bug#78910: tail does not support -r added by POSIX.1-2024

From: Bruno Haible <[email-masked]>
Date: Mon, 30 Jun 2025 01:42:15 +0200

Jim Meyering wrote:
> That is an option no GNU system needs, since they've all had tac since
> before 1992-era textutils.

But 'tac' does not have a line-number-limit argument.

The POSIX rationale [1] has

  "While both
     tail -n$n | tac
   and
     tac | head -n$n
   can be used to output a fixed length of reversed line output, the
   standard developers decided that it was preferable to have a single
   utility tail -r -n$n for the same purpose."

The second of these alternatives, 'tac | head -n$n' will not work well
with non-seekable files: it requires 'tac' to buffer the *entire* input
(as huge as it may be), before extracting a few lines of it.

The first alternative looks better: 'tail -n$n | tac'. But thinking
through it, it seems the logic that 'tail' uses for 'tail -n$n' is
also nearly suitable for 'tail -r -n$n':
  - In function file_lines(), instead of calling dump_remainder at the
    end, the loop would call xwrite_stdout once for each line (with
    special considerations for lines that span more than 1 buffer).
  - In function pipe_lines(), all the relevant data is in memory at
    the end. It's only a question of doing the xwrite_stdout calls
    on smaller pieces and in reverse order.

When implemented this way, this will be more efficient than to spawn
'tac' as a separate subprocess.

Collin Funk wrote:
> But I agree that duplicating parts of 'tac' into
> 'tail' does not seem ideal.

Which parts of the 'tac' program would need to be reused in 'tail'?
Maybe the output() function?

In any case, the technique for avoiding code duplication is well-known.
The programs 'cp', 'mv', 'install' have overlapping functionality
without necessitating duplicated code.

Bruno

[1] https://pubs.opengroup.org/onlinepubs/9799919799/utilities/tail.html