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
    – Haz
    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.
    – jordanm
    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.

Not the answer you're looking for? Browse other questions tagged .