216
wc -l file.txt

outputs number of lines and file name.

I need just the number itself (not the file name).

I can do this

 wc -l file.txt | awk '{print $1}'

But maybe there is a better way?

pogibas
  • 27,303
  • 19
  • 84
  • 117
  • 28
    `wc -l < file.txt` does the job precisely and concisely. – Jonathan Leffler Apr 19 '12 at 23:55
  • 2
    Possible duplicate of [get just the integer from wc in bash](http://stackoverflow.com/questions/3746947/get-just-the-integer-from-wc-in-bash) – Ciro Santilli OurBigBook.com Nov 19 '15 at 23:05
  • 5
    This is a question I've looked up twice now. This behavior of wc is unintuitive and anti-paradigmatic for -nix usual terseness. That terseness is there for a reason, because you *exactly do not* want to work around all kinds of fluffy redundancy. After all, I *know* the file name, don't I? What I want is the line count. – Peter - Reinstate Monica Dec 14 '18 at 11:53
  • 2
    @Peter-ReinstateMonica You can run `wc` with multiple arguments (`wc -l *.txt) in which case you will get a line for each file and need to distinguish them. – Kaligule Apr 02 '21 at 19:18

10 Answers10

308

Try this way:

wc -l < file.txt
Dave Jarvis
  • 30,436
  • 41
  • 178
  • 315
Norman Ramsey
  • 198,648
  • 61
  • 360
  • 533
  • 6
    In AIX,ksh, this will always have a space preceeding the number. We have to use | awk '{print $1}' or a cut, to trim off the spaces. Another way to trim would be to enclose with an echo. – rao Feb 18 '14 at 02:58
  • @rao is correct, this will add a space before the number. My solution solves this and is simpler than awk or cut. – Desi Cochrane Apr 19 '15 at 09:17
  • 1
    @rao There is no space with bash. Where does the space come from in ksh? `wc -l` should not emit one, and why would ksh prepend the standard output of a program with a space? – Peter - Reinstate Monica Jul 12 '17 at 12:53
  • 1
    While this is the correct workaround (and it is easy enough that wc never got amended), it likely is slower and unintuitive. For one, I'd expect something like `4711 [stdin]` as the output. – Peter - Reinstate Monica Dec 14 '18 at 10:58
  • Also consider pairing with `printf "%'d"`, which takes care of the space and prints out large numbers nicely. – Leo Apr 02 '20 at 01:39
  • 1
    Can someone explain why this works? What is the `<` doing? – mbj Sep 22 '20 at 18:02
  • @rao Interesting. Where does the space come from? – Peter - Reinstate Monica Apr 02 '21 at 20:19
33
cat file.txt | wc -l

According to the man page (for the BSD version, I don't have a GNU version to check):

If no files are specified, the standard input is used and no file name is displayed. The prompt will accept input until receiving EOF, or [^D] in most environments.

pjmorse
  • 9,204
  • 9
  • 54
  • 124
21

To do this without the leading space, why not:

wc -l < file.txt | bc
Desi Cochrane
  • 617
  • 1
  • 7
  • 14
  • I get syntax errors with this (Ubuntu 14.04). I think there is a problem with the filename. – MERose Jul 07 '15 at 23:34
  • 1
    On a RHEL 6.7 it raises errors: $ wc -l file.csv | bc (standard_in) 1: syntax error (standard_in) 1: illegal character: N (standard_in) 1: syntax error (standard_in) 1: syntax error – Rodrigo Hjort May 19 '16 at 20:09
  • 3
    I also get a parse error, but you can combine this with the other answer to use `wc -l < file.txt` to fix the parse error and remove the space: `wc -l < file.txt | bc` – jangosteve Aug 16 '16 at 16:28
17

Comparison of Techniques

I had a similar issue attempting to get a character count without the leading whitespace provided by wc, which led me to this page. After trying out the answers here, the following are the results from my personal testing on Mac (BSD Bash). Again, this is for character count; for line count you'd do wc -l. echo -n omits the trailing line break.

FOO="bar"
echo -n "$FOO" | wc -c                          # "       3"    (x)
echo -n "$FOO" | wc -c | bc                     # "3"           (√)
echo -n "$FOO" | wc -c | tr -d ' '              # "3"           (√)
echo -n "$FOO" | wc -c | awk '{print $1}'       # "3"           (√)
echo -n "$FOO" | wc -c | cut -d ' ' -f1         # "" for -f < 8 (x)
echo -n "$FOO" | wc -c | cut -d ' ' -f8         # "3"           (√)
echo -n "$FOO" | wc -c | perl -pe 's/^\s+//'    # "3"           (√)
echo -n "$FOO" | wc -c | grep -ch '^'           # "1"           (x)
echo $( printf '%s' "$FOO" | wc -c )            # "3"           (√)

I wouldn't rely on the cut -f* method in general since it requires that you know the exact number of leading spaces that any given output may have. And the grep one works for counting lines, but not characters.

bc is the most concise, and awk and perl seem a bit overkill, but they should all be relatively fast and portable enough.

Also note that some of these can be adapted to trim surrounding whitespace from general strings, as well (along with echo `echo $FOO`, another neat trick).

Community
  • 1
  • 1
Beejor
  • 8,606
  • 1
  • 41
  • 31
  • 2
    `echo $(printf '%s' "$FOO" | wc -c)` is one of the rare occasions when [`echo` with a command subshitution](http://www.iki.fi/era/unix/award.html#echo) isn't useless. – tripleee Nov 06 '18 at 18:27
  • @tripleee Whoa... based on your code, `echo \`echo $FOO\`;` also acts like a String.trim() command on a variable! That's amazingly handy. I'll also add your line to my answer. – Beejor Nov 06 '18 at 19:19
  • Perhaps for context see also [When to wrap quotes around a shell variable](/q/10067266) – tripleee Nov 07 '18 at 05:49
  • ... as well as [Why is `printf` better than `echo`?](https://unix.stackexchange.com/questions/65803/why-is-printf-better-than-echo) – tripleee Nov 07 '18 at 05:50
12

How about

wc -l file.txt | cut -d' ' -f1

i.e. pipe the output of wc into cut (where delimiters are spaces and pick just the first field)

doubleDown
  • 8,048
  • 1
  • 32
  • 48
Neil Albert
  • 129
  • 1
  • 2
  • 5
    this isn't any better than the `wc -l file.txt | awk '{print $1}'` OP tried. – doubleDown Aug 06 '13 at 00:16
  • 1
    Faster than the `wc -l < file.txt` method. But must use `| cut -d' ' -f2` on BSD, as long as the `wc` command returns a leading space, example: " 34068289 file.txt", instead of "34068289 file.txt". – Sopalajo de Arrierez Jan 07 '18 at 16:53
  • @doubleDown well, using awk is like using a CNC machine to cut a board instead of a saw. Use a saw for sawing. – Peter - Reinstate Monica Dec 14 '18 at 10:55
  • 2
    This will not work on a Mac (BSD based). The number of leading spaces depends on the padding, so the field value will depend on the result. One of the solutions above will be much better. – marco Nov 18 '20 at 00:31
  • @SopalajodeArrierez: Why would this be faster than the input redirection method? – einpoklum Aug 08 '21 at 14:34
  • @einpoklum I don't know why, but on my FreeBSD v10 the test was faster . Maybe the piping is a more efficient way than input redirection due to avoid disk usage, at least on big files. – Sopalajo de Arrierez Aug 10 '21 at 12:41
7

How about

grep -ch "^" file.txt
MeIsMich
  • 71
  • 1
  • 1
  • 5
    Nice. Very original/creative use of `grep` but checking this it turns out (unsurprisingly) to be 2x to 6x slower than the simpler/straightforward `wc` method in my tests. – arielf Apr 21 '17 at 04:41
3

Obviously, there are a lot of solutions to this. Here is another one though:

wc -l somefile | tr -d "[:alpha:][:blank:][:punct:]"

This only outputs the number of lines, but the trailing newline character (\n) is present, if you don't want that either, replace [:blank:] with [:space:].

  • 1
    This has the issue when the file name has a number in it. For example for the file `test9` with 1 line in it, the output will be 19. – Raphael Ahrens Jan 31 '20 at 10:24
3

Another way to strip the leading zeros without invoking an external command is to use Arithmetic expansion $((exp))

echo $(($(wc -l < file.txt)))
maxthoursie
  • 431
  • 3
  • 4
1

Best way would be first of all find all files in directory then use AWK NR (Number of Records Variable)

below is the command :

find <directory path>  -type f | awk  'END{print NR}'

example : - find /tmp/ -type f | awk 'END{print NR}'

RavinderSingh13
  • 130,504
  • 14
  • 57
  • 93
user128364
  • 4,533
  • 3
  • 20
  • 12
0

This works for me using the normal wc -l and sed to strip any char what is not a number.

wc -l big_file.log | sed -E "s/([a-z\-\_\.]|[[:space:]]*)//g"

# 9249133
joseluisq
  • 508
  • 1
  • 7
  • 19