4

So I'm working on a script that will accept arguments that are text files, and should output the total number of lines in those files.  For example, if I say

./myScript file1 file2 file3 

it will print

10 total 

(let us assume that the sum of all the lines from those three files is 10).

I know how to go over all the arguments.  I also know that, to get the number of lines in a file, I would say:

wc -l < fileName 

However, how can I make that into an "int" that I can add to some sort of cumulative sum?

3 Answers 3

3

You can accomplish your goal simply by using cat and a pipeline:

cat "$@" | wc -l 

If you really wanted to sum manually, you can do this with awk:

for f in "$@"; do wc -l < "$f" done | awk '{ sum+=$1 } END { print sum }' 

Or if you really wanted to parse the last line of wc, removing the string "total":

wc -l "$@" | awk 'END { print $1 }' 
2
  • Thanks for the response. Can you tell me what your second code does? Not so familiar with awk Commented Sep 20, 2015 at 4:29
  • @haz it adds the first column of each line to the "sum" variable (which starts at 0) and then prints it after all lines have been read. Commented Sep 20, 2015 at 4:32
2

Building on jordanm’s answer:

1. Pipe all the data through a single instance of wc -l

     if [ "$#" -gt 0 ] then cat -- "$@" | wc -l else echo 0 fi 
    or
     
     cat -- /dev/null "$@" | wc -l 
  • Use -- "$@" to guard against filenames beginning with -.
  • Avoid invoking cat with no arguments, as that will cause it to read the standard input.
  • Note that cat a_single_file | something is the classic form of the dreaded Useless Use of Cat, but cat one_or_more_file(s) | something can be OK (although it’s still not ideal).

2. Rely on the fact that wc issues a “total” line

     if [ "$#" -gt 0 ] then wc -l -- /dev/null "$@" | tail -1 else echo 0 total fi 
    or
     
     wc -l -- /dev/null /dev/null "$@" | tail -1 
  • Note that wc issues a total line only if it has at least two filename arguments.

3. Use awk without using wc

     if [ "$#" -gt 0 ] then awk 'END {print NR}' -- "$@" else echo 0 fi 
    or
     
     awk 'END {print NR}' -- /dev/null "$@" 

Warning:

The above commands will not all produce the same answer if any of the files end with a character other than newline.

1
sed -ne\$= files... 

Just hand sed as many filenames as you want in place of files... and, when it has read all of them, it will report the =line-number of the very $last in its input.

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.