3

How to print the length of all *.txt files in a directory?

Eg: Directory content:

FileA.txt 
FileB.txt
FileC.txt 
FileA.csv

*.txt length:

less FileA.txt | wc -l 
43
less FileB.txt | wc -l 
13
less FileC.txt | wc -l 
3

Desired output (write to output file):

43
13
3

(I am trying, with no success: ls *.txt| while read FN; do wc -l < $FN >> output; done - outputs empty file)

1
  • 2
    I do not see any recursion here. – Dubu Nov 18 '15 at 17:31
4

Some alternatives:

With GNU sed:

sed -sn '$=' ./*.txt

(note that it will not report the number for empty files, and (contrary to wc -l), will count spurious data after the last newline character as an extra line).

Wildcard patterns like *.txt, by default don't include hidden files.

With GNU awk:

awk 'ENDFILE{print FNR}' ./*.txt

This time, you'll get a 0 for empty files. Same note about spurious data as for GNU sed.

$ seq 10 > a.txt; : > b.txt; printf spurious > c.txt; seq 20 > .hidden.txt; echo test > $'a\n3 4.txt'
$ wc -l ./*.txt
 1 ./a
3 4.txt
10 ./a.txt
 0 ./b.txt
 0 ./c.txt
11 total
$ wc -l ./*.txt | awk '/\//{print $1}'
1
10
0
0
$ sed -ns '$=' ./*.txt
1
10
1
$ awk 'ENDFILE{print FNR}' ./*.txt
1
10
0
1

Recursively, if you want a list sorted by filename, with zsh or ksh -o globstar or bash -O globstar or yash -o extended-glob:

wc -l .//**/*.txt | awk '/\/\//{print $1}'
sed -ns '$=' ./**/*.txt
awk 'ENDFILE{print FNR}' ./**/*.txt
5
wc -l -- *.txt

or if you don't want the filenames in the output (here assuming file names don't contain newline characters):

wc -l -- *.txt | awk '{print $1}'

If there are too many *.txt files to fit on a single shell command line and assuming your find supports -maxdepth:

find . -maxdepth 1 -type f -name '*.txt' -exec wc -l {} + | 
    awk '$2 != "total" {print $1}'

(note that that one, contrary to the previous one will not sort the file list, will include hidden files and exclude non-regular files including symlinks to regular files).

You can, of course, redirect the output of any of these to a file or pipe it into another program for more processing.

4
  • Thanks! The findsolution worked for me! – dovah Nov 18 '15 at 11:09
  • @StéphaneChazelas - so it will, i forgot about that. fixed. slower but fixed. wc really needs some extra options like --no-total and --no-filenames – cas Nov 18 '15 at 11:36
  • fixed again, this time in awk. back to being fast again. – cas Nov 18 '15 at 11:43
  • 1
    Best is to look for the / (see my answer) to also avoid problems with filenames containing newline characters. – Stéphane Chazelas Nov 18 '15 at 12:10
1

You can use wildcards in combination with wc command to get the number of lines of each file:

wc -l *.txt

The output will be as follows:

13 a.txt

29 b.txt

3 d.txt

45 total

If you dont wnat the total lines you can pipe it to the head command provided you have more than one file to count:

wc -l *.txt |head -n -1

If you want ony the number of line and not the file:

wc -l *.txt |head -n -1 |awk '{print $1}'

Alternately you can try with for loops to avoid the total count whether there is one file or more than one file ,but its the ugliest way:

for i in $(ls *.txt);do wc -l $i;done

2
  • 2
    The total line is only printed if there are more than 1 input files. – Stéphane Chazelas Nov 18 '15 at 11:20
  • Yes, you are absolutely correct. – Kheshav Sewnundun Nov 18 '15 at 11:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.