nl Command: Numbering Lines

nl Command: Numbering Lines

What You'll Learn

  • How to add line numbers with the nl command
  • The key difference between nl and cat -n (how they treat blank lines)
  • How to change the number width, separator, start value, increment, and format
  • How to quickly point to "which line" in a log or source file

Quick Summary

  • Just need numbers fast → nl file
  • Want blank lines numbered too → nl -b a file
  • cat -n also numbers every line (handy when you don't need options)

1. What Is the nl Command?

Conclusion: nl (number lines) prints each line of text with a line number in front. By default it skips blank lines.

Lina: I want to read a file while keeping track of "which line is which." Do I really have to count with my finger?
Linny-senpai: No, the nl command prints the text with line numbers for you. nl stands for "number lines."
Lina: I wish I'd known sooner. How do I use it?
Linny-senpai: Just pass it a file name: nl filename.

Let's try it on a three-line file called memo.txt.

$ cat memo.txt
apple
orange
grape

Run it through nl and each line gets a number in front.

$ nl memo.txt
     1	apple
     2	orange
     3	grape

nl basics

nl filename puts a right-aligned line number in front of each line. The number and the text are separated by a tab.

2. How Is nl Different from cat -n?

Conclusion: The big difference is blank lines. By default nl does not number blank lines, while cat -n numbers every line.

Lina: But cat -n also adds line numbers, right? What's the difference?
Linny-senpai: Good question. The main difference is how they treat blank lines. Let's see it.

Here is list.txt with blank lines in the middle.

$ cat list.txt
red

blue

green

Run nl and the blank lines get no number.

$ nl list.txt
     1	red

     2	blue

     3	green

cat -n, on the other hand, numbers every line, blanks included.

$ cat -n list.txt
     1	red
     2
     3	blue
     4
     5	green

Which one to use

What you want Command
Number only lines with content nl file
Number every physical line, blanks too cat -n file
Fine control over width and format nl (rich options)
Lina: So nl numbers the "meaningful" lines.
Linny-senpai: Right. And as we'll see, nl lets you tune the width and separator, so it's great when you want the output to look clean.

3. Numbering Blank Lines Too: -b a

Conclusion: Add -b a to number every line, blanks included. -b sets the body numbering style.

When you want blank lines numbered too, use -b a. The a means "all" lines.

$ nl -b a list.txt
     1	red
     2
     3	blue
     4
     5	green

Main -b styles

  • -b a: number all lines (all)
  • -b t: number only non-empty lines (default, t for text)
  • -b n: number no lines (none)
Lina: Since the default is -b t, blank lines get skipped unless I say otherwise.
Linny-senpai: Exactly. When you want everything numbered, reach for -b a.

4. Shaping the Numbers: -w / -s

Conclusion: Use -w for the number column width and -s for the separator between number and text. Defaults are width 6 and a tab.

4-1. Change the width (-w)

By default the number column is six characters wide. -w sets the width.

$ nl -w 3 memo.txt
  1	apple
  2	orange
  3	grape

4-2. Change the separator (-s)

The number and the text are separated by a tab by default. -s sets any string you like.

$ nl -s '. ' memo.txt
     1. apple
     2. orange
     3. grape
Lina: With -s '. ' I get "1. apple," like a bulleted list.
Linny-senpai: Yes. The separator can include spaces, so combine -w and -s to build a clean, readable list.

5. Start Value and Increment: -v / -i

Conclusion: -v sets the starting number and -i sets the increment. Start at 100, or count by 2, as needed.

5-1. Change the start value (-v)

-v is the first number. To start at 100:

$ nl -v 100 memo.txt
   100	apple
   101	orange
   102	grape

5-2. Change the increment (-i)

-i is how much each line adds. To count by 2, use -i 2.

$ nl -i 2 memo.txt
     1	apple
     3	orange
     5	grape

-v and -i combine: nl -v 10 -i 10 memo.txt numbers 10, 20, 30.

6. Zero Padding and Alignment: -n

Conclusion: -n sets the number format: rz for zero padding, ln for left alignment, rn (default) for right alignment.

-n controls how the number is displayed.

$ nl -n rz -w 3 memo.txt
001	apple
002	orange
003	grape

-n format values

Value Meaning
rn Right-aligned, no padding (default)
rz Right-aligned, zero-padded
ln Left-aligned

7. Using nl in a Pipe

Conclusion: With no file name, nl reads standard input, so you can pipe another command's output through it to add line numbers.

Leave out the file name and pipe into nl to number the previous command's output.

$ ls /etc | nl
     1	hostname
     2	hosts
     3	passwd
Lina: Now I can say which item is which at a glance.
Linny-senpai: Right. Piping grep results into nl to count "which match number" is a common move too.

If the piped input contains blank lines, the default skips numbering them. To count items exactly, add -b a or use cat -n.

8. Mini Exercises: Try It Yourself

Conclusion: Three tasks (create a file, number with blanks, adjust the format) let you practice the nl basics by hand.

Lina: I want to learn by doing!
Linny-senpai: Great, I've got three for you. First, make a practice file.
Linny-senpai: printf 'a\n\nb\n\nc\n' > sample.txt

Task 1: Print sample.txt with line numbers using nl (blank lines can stay unnumbered).

Show hint

Just pass the file name: nl filename.

Sample answer
$ nl sample.txt

Task 2: Print the same sample.txt with blank lines numbered too.

Show hint

Set the body numbering style to all with -b a.

Sample answer
$ nl -b a sample.txt

Task 3: Print sample.txt with 3-digit zero-padded numbers (001, 002, ...).

Show hint

Combine the format -n rz with width -w 3.

Sample answer
$ nl -n rz -w 3 sample.txt

9. Copy-Paste Templates

Conclusion: Keep the common patterns handy: basic, all lines, formatting, and piping.

Common patterns to keep around

# Basic (number non-empty lines)
nl file.txt

# Number every line, blanks included
nl -b a file.txt

# Width 3, dot separator
nl -w 3 -s '. ' file.txt

# Start at 100, step by 2
nl -v 100 -i 2 file.txt

# 3-digit zero padding
nl -n rz -w 3 file.txt

# Pipe another command's output through nl
ls /etc | nl

Next Reading