awk FNR: Per-File Line Numbers and File Joins
awk FNR is the record number within the current file, resetting to 1 each time awk opens a new input.
When awk processes several files, NR keeps climbing but FNR restarts per file. The difference powers the classic NR==FNR two-file join.
What it does
FNR counts records within the current file and resets to 1 when the next file begins, while NR counts across all files. The expression NR==FNR is true only while reading the first file, which lets you load it into an array before processing the second.
Common usage
# per-file line numbers with the filename
awk '{print FILENAME, FNR, $0}' a.log b.log
# the NR==FNR join: keep lines of file2 whose key is in file1
awk 'NR==FNR{seen[$1]=1; next} seen[$1]' keys.txt data.txt
# print the header of each file
awk 'FNR==1' *.csvVariables and idioms
| Expression | What it does |
|---|---|
| FNR | Record number within the current file |
| NR | Record number across all files |
| FILENAME | Name of the file currently being read |
| NR==FNR{...; next} | Run a block only for the first file, then skip to the next line |
| FNR==1 | Match the first line of each file |
In CI
The NR==FNR idiom replaces a join when you need to filter one report by keys from another, with no temp files or sort. The next after the first-file block is what stops those lines from falling through into the second-file logic.
Common errors in CI
Omitting next in the NR==FNR block makes first-file lines also run the second-file action, double-counting or mis-filtering. FILENAME is empty when input comes from stdin (a pipe), so the FILENAME idioms only work on named file arguments. Mixing up NR and FNR in a join silently keys off the wrong record number.