I'm sure there are many ways to do this: how can I count the number of lines in a text file?

$ <cmd> file.txt
1020 lines

The standard way is with wc, which takes arguments to specify what it should count (bytes, chars, words, etc.); -l is for lines:

$ wc -l file.txt
1020 file.txt
  • How do I count the lines in a file if I want to ignore comments? Specifically, I want to not count lines that begin with a +, some white space (could be no white space) and then a %, which is the way comment lines appear in a git diff of a MATLAB file. I tried doing this with grep, but couldn't figure out the correct regular expression.
    – Gdalya
    Jul 11 '13 at 1:36
  • @Gdalya I hope the following pipeline will do this (no tests were perfomed): cat matlab.git.diff | sed -e '/^\+[ ]*.*\%$/d' | wc -l. /regexp/d deletes a line if it matches regexp, and -e turns on an adequate (IMNSHO) syntax for regexp.
    – dbanet
    Nov 6 '13 at 21:29
  • 2
    Why not simply grep -v '^+ *%' matlab.git.diff | wc -l?
    – celtschk
    Jul 6 '14 at 19:51
  • @celtschk , as long as this is usual in comment lines: is it possible to modify your grep command in order to consider as comment cases like " + Hello" (note the space(s) before the +)? Jan 18 '15 at 20:46
  • 1
    @SopalajodeArrierez: Of course it is possible: grep -v '^ *+' matlab.git.diff | wc -l (I'm assuming the quote signs were not actually meant to be part of the line; I also assume that both lines with and without spaces in front of the + are meant to be comments; if at least one space is mandatory, either replace the star * with \+, or just add another space in front of the star). Probably instead of matching only spaces, you'd want to match arbitrary whitespace; for this replace the space with [[:space:]]. Note that I've also removed matching the % since it's not in your example.
    – celtschk
    Feb 14 '15 at 15:02

Steven D forgot GNU sed:

sed -n '$=' file.txt

Also, if you want the count without outputting the filename and you're using wc:

wc -l < file.txt

Just for the heck of it:

cat -n file.txt | tail -n 1 | cut -f1
  • 2
    Or grep -c '', or tr -dc '\n' | wc -c, or nl -ba -nln | tail -n 1 |sed -e 's/[^0-9].*//'... Is any of these useful in itself (as opposed to things to build upon to make a program that does more than counting lines), other than wc -l and pure (ba)sh? Dec 3 '10 at 1:58
  • 1
    @Gilles: I think the phrase "many ways" in the question triggered a challenge that Steve and I rose to. Dec 3 '10 at 2:03
  • 1
    @Gilles: sed 's/.*//' file.txt | uniq -c Dec 3 '10 at 2:30
  • 2
    @Gilles: Oh, you meant first. uniq -c -w 0 file.txt and you can cut -c -7 to keep only the number. Or, more POSIXly: uniq -c file.txt | awk '{c+=$1}END{print c}'. How about dc (even though it's not POSIX)? uniq -c file.txt | cut -c -7 | sed '$alax' | dc -e '[pq]sb[+z1=blax]sa' -. bc is POSIX: uniq -c file.txt | cut -c -7 | sed -n ':a;${s/\n/ + /gp;b};N;ba' | bc. The easy answer if you assume a limited line length: uniq -c -f 100000 file.txt. Dec 3 '10 at 16:21
  • 1
    @JosipRodin: Quotes added Oct 18 '15 at 0:09

As Michael said, wc -l is the way to go. But, just in case you inexplicably have bash, perl, or awk but not wc, here are a few more solutions:


$ LINECT=0; while read -r LINE; do (( LINECT++ )); done < file.txt; echo $LINECT

Perl Solutions

$ perl -lne 'END { print $. }' file.txt

and the far less readable:

$ perl -lne '}{ print $.' file.txt

Awk Solution

$  awk 'END {print NR}' file.txt

Word of warning when using

wc -l

because wc -l functions by counting \n, if the last line in your file doesn't end in a newline effectively the line count will be off by 1. (hence the old convention leaving newline at the end of your file)

Since I can never be sure if any given file follows the convention of ending the last line with a newline or not, I recommend using any of these alternate commands which will include the last line in the count regardless of newline or not.

sed -n $= filename
perl -lne 'END { print $. }' filename
awk 'END {print NR}' filename
grep -c '' filename
  • nice summary. And welcome to unix & linux
    – Sebastian
    Sep 18 '14 at 15:29
  • Hm is the last piece really line?
    – gena2x
    Sep 18 '14 at 19:48
  • 1
    I'm sure it depends on everyone's usecase; for the 'last piece' is usually a line of text that someone didn't cap off with a newline. The usecase I most often encounter is a file with a single string of text that does not end in a newline. wc -l would count this as "0", when I would otherwise expect a count of "1". Sep 23 '14 at 16:22
  • It is not the count of wc that will be off by one, but your count: While in Windows (and DOS before it), the CR/LF sequence is a line separator, on Unix the LF character is a line terminator. That is, without a newline at the end, you don't have a line (and strictly speaking, not a valid text file).
    – celtschk
    Feb 7 '20 at 9:15

In case you only have bash and absolutely no external tools available, you could also do the following:

while read
done <file.txt
echo $count

Explanation: the loop reads standard input line by line (read; since we do nothing with the read input anyway, no variable is provided to store it in), and increases the variable count each time. Due to redirection (<file.txt after done), standard input for the loop is from file.txt.

  • This is a very inefficient way to do it. Remember, bash reads are slow. Feb 7 '20 at 1:51
  • @codeforester: That's true, but (a) it was a solution for when you have no other tool available, and (b) slow doesn't mean unawaitable. I just tried with a text file of 125MB (taking an actual text file and concatenating it a thousand times) and more than 2.6 million lines, and it took slightly less than 14 seconds. Not nothing — the tools do it in a fraction of a second — but certainly awaitable.
    – celtschk
    Feb 7 '20 at 8:58
  • This would miscount if any line ended with a backslash.
    – Kusalananda
    Apr 11 at 17:54

You can always use the command grep as follows:

grep -c "^" file.txt

It will count all the actual rows of file.txt, whether or not its last row contains a LF character at the end.


If you're looking to count smaller files a simple wc -l file.txt could work.

Looking for an answer to this question myself, working with large files that are several gigs, I found the following tool:


Also, depending on your system configuration--if you're using an older version of wc you might be better off piping larger chunks with dd like so:

dd if={file_path} bs=128M | wc -l

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.