Skip to content
Linux Basics: Match Sorted Text Records with GNU join

Linux Basics: Match Sorted Text Records with GNU join

October 27, 2026

Two simple exports may share an identifier but contain different columns. GNU join matches sorted input records by a key. Use a deliberately small delimiter-separated fixture to see matched rows and missing partners.

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-join.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 'c Cara\na Ada\nb Ben\n' > people.txt
printf 'a ready\nc waiting\nd new\n' > states.txt
sort -k1,1 people.txt > people.sorted
sort -k1,1 states.txt > states.sorted
printf 'Matched:\n'
join --check-order people.sorted states.sorted > matched.txt
cat matched.txt
test "$(wc -l < matched.txt)" -eq 2
printf 'All keys:\n'
join --check-order -a 1 -a 2 -e missing -o 0,1.2,2.2 \
  people.sorted states.sorted
printf 'People without a state:\n'
join --check-order -v 1 people.sorted states.sorted

Run it:

bash demonstrate-gnu-join.sh

Observed output:

Matched:
a Ada ready
c Cara waiting
All keys:
a Ada ready
b Ben missing
c Cara waiting
d missing new
People without a state:
b Ben

Read the result

Both files are sorted by the same field under the same C locale. The default output contains the join key followed by non-key fields from each matching row. -a 1 -a 2 retains unpaired records from both sides. The explicit -o layout makes missing fields visible through -e; -v 1 selects only unmatched records from the first file.

Apply it carefully

Duplicate keys produce combinations of matching records, so check key uniqueness when expecting one row per identifier. Default whitespace field parsing is not CSV parsing: quoted commas, embedded spaces, and multiline values require a format-aware tool. Keep sorted outputs separate from inputs. --check-order turns ordering mistakes into failures rather than trusting incomplete matches.

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-join.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