I usually do this

$ wc questions
  33   36 3105 questions
$ seq 1 33 > nums
$ paste nums questions
1       Content
2       ...
33      End Content

but I feel there could be faster way to do this, without the bad-looking dummy file. How with some basic *ix -tool? Any simpler way to do it? I use Vim so I am happy also with Vim-based solution but simple unix-based solution also works (actually probably better in some cases, I can always spawn inside the editor).

Below a general case.




1. A
2. B
3. C
N. X

6 Answers 6


This is exactly what nl is for. For example, assuming file.txt contains your sample input, and you want it to look like your sample output, you could do:

nl -nln '-s. ' file.txt

The manpage for nl goes into greater detail on its use. It gives you a lot of control over the output format.

  • Wow. I've been using *IX since the mid 1980's and I'd never used or heard of nl.
    – Kyle Jones
    Mar 8, 2012 at 4:37
  • I had to look it up, but according to FreeBSD, it dates to SVR2. Mar 8, 2012 at 4:46
  • surely not POSIX. It's not on OpenBSD. Though I knew it existed before but I will strongly advise not to use it in scripts. A little "idx=0;for i in cat file; do echo $idx $i; idx=eval $idx + 1 ; done" should do the trick (didn't test, but surely you see the point). You could use an editor like vim/view to look at the file and configure it to print line numbers too, you'll have syntax colors as well hey.
    – Aki
    Mar 8, 2012 at 5:10
  • 2
    @Aki: The FreeBSD manpage from 4.7-RELEASE onward claims it conforms to POSIX.1, and it's listed in the Single Unix Specification version 2. Mar 8, 2012 at 14:21
  • 5
    To number all line, it also needs -ba. otherwise it numbers only non-blank lines and yet still prints the un-numbered blank lines, meaning that the line numbers don't increment to reflect the actual number of newlines... This fixes it: nl -nln -ba -s'. '
    – Peter.O
    Mar 8, 2012 at 23:11

I'm surprised cat -n hasn't been mentioned by now.

  • 3
    Too standard. It can make things portable...
    – Aki
    Mar 8, 2012 at 5:13
  • I just mentioned that cat -n in another comment. I was surprised that the -n option isn't part of the Single Unix Specification.
    – D.Shawley
    Mar 8, 2012 at 22:36

Just for the completeness of this list, sed can also do it:

sed '=' questions | sed 'N;s/\n/. /'

Sadly the = command prints the line numbers on separate line, so only a separated sed call can beautify the formatting.


In Vim you could add line numbers to the actual text of a buffer like this:

:%s/^/\=printf('%5d. ',line('.'))

The \= (see :help sub-replace-expression) lets the replacement string be treated as a VimL expression. The expression used here is a simple formatting of the current line number.

You could make it a bit fancier by automatically calculating and using a minimal width (instead of the “hard coded” 5, as above) for the current number of lines in the file:

:%s/^/\=printf('%*d. ',len(line('$')),line('.'))

Or, left-justified:

:%s/^/\=printf('%d.%*s ',line('.'),len(line('$'))-len(line('.')),'')

Of course, if you just want to see the line numbers and do not care to have them actually in the buffer’s data, then you should just use

:set number

From the shell, you might find cat -n or pr -tn useful.

  • Sweet. He could even map the commands to a key. But for the first example I'd rather write a shell script and execute it than open the file on vim and enter this command each time (or press a key) and quit vim then print my file.
    – Aki
    Mar 8, 2012 at 5:12

Not sure what your constraints are regarding the separation between the number and the data, but i'd do: grep -n '^' questions. That would output:


33:End Content
  • 1
    Using just . as the regex, it will not output blank lines... Using '.*' will .
    – Peter.O
    Mar 8, 2012 at 8:10
  • 2
    So will ^ as the regex.
    – Ladadadada
    Mar 8, 2012 at 17:13

Some other solutions:

Exactly what you were doing, without the temporary file:

seq 1 $(wc -l questions | cut -f 1 -d " ") | paste - questions

But cat -n is much better as above fails if the questions file change between the call to wc and paste.

If you want to avoid creating a process you could:

{ N=1; while read line; do printf "%d %s\n" $N "$line"; N=$(($N + 1)); done; } < questions

But do not try the above if you have a large file, especially because the following bash bug.

  • You can spare the cut. When wc processes STDIN outputs no file name: seq 1 $(wc -l < questions) | paste - questions
    – manatwork
    Mar 16, 2012 at 15:59
  • In this case, cut does not process STDIN output, it process the questions file.
    – jfg956
    Mar 16, 2012 at 16:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy