Skip to content
Linux Basics: Reverse Record Order with GNU tac

Linux Basics: Reverse Record Order with GNU tac

October 27, 2026

A small event file is often easiest to inspect from its last record. GNU tac reverses record order, not characters. Compare newline records with an explicit separator to see where each separator belongs.

Prepare a scratch directory

Tested on Linux with GNU coreutils 9.7 and GNU Bash 5.2.37. You need the named runtime, Bash, a text editor, and the standard mktemp, rm, and rmdir utilities. The script creates a separate temporary fixture directory and removes only that directory on exit. It does not operate on your existing files.

Keep using the same terminal. Stop if setup fails, before saving the source:

start_dir="$PWD"
work_dir="$(mktemp -d)" || exit 1
cd -- "$work_dir" || exit 1

Run the example

Save this as demonstrate-gnu-tac.sh:

#!/usr/bin/env bash
set -euo pipefail
export LC_ALL=C
fixture_dir="$(mktemp -d)"
trap 'rm -rf -- "$fixture_dir"' EXIT
cd -- "$fixture_dir"
printf 'start\nwork\nfinish\n' > events.txt
printf 'Newest line first:\n'
tac events.txt > reversed.txt
cat reversed.txt
tac reversed.txt > restored.txt
cmp events.txt restored.txt
printf 'Custom records, separator after each record:\n'
printf 'red|green|blue|' | tac -s '|'
printf '\nSeparator before each record:\n'
printf '|red|green|blue' | tac -b -s '|'
printf '\nRound trip: identical\n'

Run it:

bash demonstrate-gnu-tac.sh

Observed output:

Newest line first:
finish
work
start
Custom records, separator after each record:
blue|green|red|
Separator before each record:
|blue|green|red
Round trip: identical

Read the result

The default record separator is a newline. Reversing this newline-terminated fixture twice restores its bytes, which cmp verifies. With -s, the selected separator normally belongs to the end of a record. -b instead attaches it to the beginning. The extra printf calls add display newlines because the custom records contain none.

Apply it carefully

Record reversal is not timestamp sorting. It only puts physically later records first. A final line without its terminating separator can interact with the preceding line when reversed; normalize or inspect that case before using a round-trip assumption. tac may need temporary storage for non-seekable input. This tutorial uses tiny data and GNU behavior, not a portable shell substitute available on every system.

The official reference describes the API and its options. The checks above cover the specific fixture, not every possible input or environment.

Clean up

Remove the source and then the empty practice directory:

rm -- demonstrate-gnu-tac.sh
cd -- "$start_dir" || exit 1
rmdir -- "$work_dir"
unset start_dir work_dir

If the directory is not empty, inspect the remaining files rather than deleting unknown contents.

Acknowledgements

This post was created with assistance from AI.

Last updated on