0

For printing number of lines in all ".txt" files of current folder, I am using following script:

for f in *.txt;
do l="$(wc -l "$f")";
echo "$f" has "$l" lines;
done 

But in output I am getting:

lol.txt has 2 lol.txt lines

Why is lol.txt printed twice (especially after 2)? I guess there is some sort of stream flush required, but I dont know how to achieve that in this case.So what changes should i make in the script to get the output as :

lol.txt has 2 lines
Gilles 'SO- stop being evil'
  • 104,111
  • 38
  • 209
  • 254
buch11
  • 872
  • 3
  • 13
  • 29
  • 1
    If you just run `wc -lol.txt` from the command line it should then be obvious what's happening – Paul R May 30 '12 at 14:15

4 Answers4

1

The filename is printed twice, because wc -l "$f" also prints the filename after the number of lines. Try changing it to cat "$f" | wc -l.

lanzz
  • 42,060
  • 10
  • 89
  • 98
  • Or read the number using `read`: `wc -l /etc/passwd | { read n rest ; echo $n ; }` – ceving May 30 '12 at 14:27
  • no but a little bit more reliable. It could be possible that there is a wc which prints /dev/stdin instead of nothing while reading from stdin. – ceving May 30 '12 at 14:51
  • I have yet to encounter such a `wc`, but I suppose it is possible. – lanzz May 30 '12 at 14:53
  • From http://pubs.opengroup.org/onlinepubs/9699919799/utilities/wc.html: `If no input file operands are specified, no name shall be written and no characters preceding the pathname shall be written.` – William Pursell May 30 '12 at 15:52
1

wc prints the filename, so you could just write the script as:

ls *.txt | while read f; do wc -l "$f"; done

or, if you really want the verbose output, try

ls *.txt | while read f; do wc -l "$f" | awk '{print $2, "has", $1, "lines"}'; done
William Pursell
  • 204,365
  • 48
  • 270
  • 300
1

You can remove the filename with 'cut':

for f in *.txt;
do l="$(wc -l "$f" | cut -f1 -d' ')";
echo "$f" has "$l" lines;
done 
utrescu
  • 374
  • 2
  • 6
1

There is a trick here. Get wc to read stdin and it won't print a file name:

for f in *.txt; do
    l=$(wc -l < "$f")
    echo "$f" has "$l" lines
done
pixelbeat
  • 30,615
  • 9
  • 51
  • 60
  • what is the exact diff between (1) l=$(wc -l < "$f") and (2) l="$(wc -l "$f")"; ??? – buch11 May 31 '12 at 01:27
  • With the redirected for, wc doesn't get a file name and wc treats this case specially and only outputs the count(s) – pixelbeat Jun 03 '12 at 01:01