-2

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.

Braiam
  • 35,991
crisron
  • 499
  • 6
    StackExchange is not a place where you can find your homework assignments made for you... You ought to specify what you tried, what failed, what results you got. – John WH Smith Dec 31 '13 at 20:06
  • We're more than happy to help, but the operative word here is help, not do your homework for you. Show us what you've got so far. – slm Dec 31 '13 at 20:22
  • 5
    We're happy to help with specific questions about your assignment, but we don't do your assignment for you. – derobert Jan 01 '14 at 01:26
  • 1
    This was not an assignment. I was reading a book on UNIX and solving the exercises. I got stuck on this so asked – crisron Jan 01 '14 at 13:16
  • 1
    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

2 Answers2

3

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.

1

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}')
slm
  • 369,824