shuf turns a list into a random order, a random sample, or a random pick, all from one small GNU coreutils command. You will finish with a small set of reliable patterns: randomising input lines, drawing a bounded sample, generating repeatable test data, and handling file names that contain spaces or newlines. The examples target GNU coreutils 9.4, the version installed on this machine.
Allow about fifteen minutes. You need a shell and the coreutils package. Every command below is an ordinary user command. Nothing needs sudo, and the examples do not alter a service or system configuration.
Start by confirming the binary and version. This prevents a copied example from silently depending on a different implementation:
$ command -v shuf
/usr/bin/shuf
$ shuf --version | sed -n '1p'
shuf (GNU coreutils) 9.4
shuf writes a random permutation of its input lines. With no file, it reads standard input. With a file name, it reads that file; a file name of - also means standard input. The normal output order is deliberately unpredictable, so verify properties such as the number of lines and membership rather than one particular order.
Checkpoint: If the first command finds another program, read that program's help before using GNU-only options. The rest of this guide describes the installed GNU command.
Put one item on each input line and pipe the list to shuf:
$ printf '%s\n' alpha bravo charlie delta | shuf
charlie
alpha
delta
bravo
The four lines will appear in a different order on most runs, but any of the 24 permutations is valid. The command does not sort, remove duplicates or interpret the words. Duplicate input lines remain duplicate output lines.
To shuffle an existing text file, pass it as the final operand:
$ shuf /path/to/items.txt
Keep the input format in mind: ordinary mode treats newline as the delimiter. A record containing an embedded newline is therefore two records, not one.
Use -n, or --head-count, to output at most a chosen number of lines:
$ printf '%s\n' red amber green blue violet | shuf --head-count=3
blue
red
violet
The result contains three different input positions when the input has at least three lines. It is a sample without replacement. If the input has fewer lines than the count, shuf outputs all of them rather than inventing extra values.
For a quick check that the count is right, discard the random content and count the lines:
$ printf '%s\n' red amber green blue violet | shuf -n 3 | wc -l
3
Do not use -n as a memory limit. shuf reads the input before producing a permutation, so very large inputs still need resources proportional to the input.
-i LO-HI treats every integer in the inclusive range as an input line:
$ shuf --input-range=1-10 --head-count=4
7
2
10
5
This gives four distinct numbers in the range 1 through 10. For a one-off random choice, use a count of one:
$ shuf -i 1-6 -n 1
4
The displayed values are examples, not promises. Check the value against the range if a script will act on it:
$ roll=$(shuf -i 1-6 -n 1)
$ case "$roll" in 1|2|3|4|5|6) printf 'valid roll: %s\n' "$roll" ;; *) exit 1 ;; esac
valid roll: 4
By default, shuf outputs a permutation and stops once each input line has been used. Add -r, or --repeat, when each selection may be made again:
$ shuf -r -n 8 -e Heads Tails
Tails
Heads
Heads
Tails
Tails
Heads
Heads
Tails
-e makes each remaining argument an input line. Combining -r with -n is the useful bounded form. Without -n, repeat mode continues indefinitely, so do not run it in an unattended pipeline unless another command supplies a stopping condition.
Shell parsing still applies before shuf sees the arguments. Quote values containing spaces:
$ shuf -e 'North Wing' 'South Wing' -n 1
South Wing
Newline-delimited pipelines are unsafe for file names that contain newlines. Use -z, or --zero-terminated, when the producer and consumer use NUL-delimited records:
$ find /path/to/tree -type f -print0 | shuf -z -n 1 | xargs -0 -r printf 'chosen: %s\n'
chosen: /path/to/tree/report with spaces.txt
find -print0 emits one NUL-terminated name per record, shuf -z preserves that delimiter while selecting one, and xargs -0 reads it the same way. The -r on GNU xargs avoids running printf when there was no input.
Do not mix delimiter modes. A plain shuf in the middle would split records at newlines, and a plain xargs would apply whitespace parsing to names.
GNU shuf can write to a file with -o. It reads all input before opening the output file, so this in-place form is supported:
$ shuf -o /path/to/items.txt < /path/to/items.txt
This changes the file's order. Treat it as a state-changing command: check the path twice, keep a backup if the ordering matters, and do not use a shell variable containing an unverified path. Recovery is to restore your backup, or regenerate the file from its original source. There is no undo stored by shuf.
For a safer workflow, write to a deliberate temporary file, inspect it, then replace the original with a separate reviewed operation:
$ tmp=$(mktemp)
$ shuf /path/to/items.txt > "$tmp"
$ wc -l /path/to/items.txt "$tmp"
$ sed -n '1,5p' "$tmp"
$ mv -- "$tmp" /path/to/items.txt
If inspection fails, remove only the temporary file with rm -- "$tmp". If the final mv succeeds, the original path now refers to the shuffled file. The mv step is the irreversible boundary for this example, so do not automate it until the count and sample look correct.
The order is random by default. GNU shuf accepts --random-source=FILE to read random bytes from a file. Save that source and use the same input and source again when you need to reproduce a test:
$ dd if=/dev/urandom of=/tmp/shuf-random.bin bs=1K count=1 status=none
$ printf '%s\n' one two three four | shuf --random-source=/tmp/shuf-random.bin
three
one
four
two
$ printf '%s\n' one two three four | shuf --random-source=/tmp/shuf-random.bin
three
one
four
two
The random-source file is test material, not a secret. Protect it from accidental deletion until the test is complete, and do not claim that saving it makes an otherwise non-deterministic program secure or cryptographically reproducible in every environment. Remove this temporary file when it is no longer needed:
$ rm -- /tmp/shuf-random.bin
-z end to end when file names may contain newlines.-o changes the target file and have a recovery path.