A file foo contains a list of filenames. Devise a single statement that stores in a variable count the total character count of the contents of these files.
2 Answers
Here's a way to do this in a single shell command.
<foo awk 'FILENAME=$0{while(getline<FILENAME>OUTPUT&&match($0,"$"))RSTOP-=RSTART}END{print-RSTOP}' | read count
This may not be the least awkward way to do it.
Be sure to tell me what your teacher thinks of it!
Some hints if you want to work it out:
- Yes, it does work, in any POSIX environment. But in order to see it, you may need to use the right shell.
- The choice of variable names may be a tad confusing (except when it isn't). Try renaming each of the and see which ones are significant.
Further hints:
• The while loop condition is (getline <INPUT > OUTPUT) && match($0, /$/) — be sure to work out what the < and > operators are here.
• If you think this isn't assigning to count, try in ksh or zsh.

- 829,060
Since apparently we're answering this question now.
Sample data
$ ls -1
afile1
afile2
afile3
filelist.txt
$ cat afile{1..3}
blah
blah
blah
Example
$ cnt=0; for i in $(< filelist.txt);do \
let cnt="cnt+$(wc -c $i | cut -d' ' -f1)";done; echo $cnt
15
In its expanded form:
$ cnt=0;
$ for i in $(< filelist.txt);do
let cnt="cnt+$(wc -c $i | cut -d' ' -f1)"
done
$ echo $cnt
The derobert's technique
One of our regulars mentioned that your instructor might have been looking for this method, which until today I was unaware of. In newer versions of the wc
command there is a --files0-from=
switch which can take a list of files and calculate the number of characters and the corresponding total.
The crux of the approach:
$ tr -s '\n' '\000' < filelist.txt | wc -c --files0-from=-
Example
$ tr -s '\n' '\000' < filelist.txt | wc -c --files0-from=-
5 afile1
5 afile2
5 afile3
15 total
This can of course be cleaned up so that the result is stored in a value. Something like this:
$ tr -s '\n' '\000' < filelist.txt | \
wc -c --files0-from=- | awk '/total/ {print $1}'
15
And finally you can store the results in a variable like so:
$ cnt=$(tr -s '\n' '\000' < filelist.txt | \
wc -c --files0-from=- | awk '/total/ {print $1}')

- 369,824
-
There's a stray quote character in your answer, but otherwise that's not a downright awful way. – Gilles 'SO- stop being evil' Jan 01 '14 at 01:49
xargs cat -- < file.list | wc -c
(assuming there's not file called-
in that list and that the list is blank separated with quotes and backslash used to escape those blanks if they occur in filenames) – Stéphane Chazelas Jan 01 '14 at 17:07