shuf shuffles correctly. Hand-rolled shuffles frequently do not, and the bias is invisible without statistical testing.
The sort-by-random antipattern
Sorting with a comparator returning a random value is the most common wrong implementation. It does not produce a uniform distribution, and the exact bias depends on the sort algorithm โ so the same code is wrong in different ways on different engines.
Fisher-Yates is the correct algorithm
Iterate from the last element down, swapping each with a randomly chosen element at or before it. Linear time, uniform distribution, a few lines of code. The common off-by-one error is choosing the swap index from the wrong range, which produces a subtly biased shuffle that still looks random.
Seed deliberately when reproducibility matters
shuf --random-source allows a fixed seed, which makes a sample reproducible. For an audit that someone may need to verify later, a reproducible sample is considerably more defensible than one nobody can regenerate.
Try it: Shuffle Lines Randomly on SeoWolf's Notepad.