12

I want to count the total number of lines in all /etc files but not the files in the sub directories, so I typed: wc -l /etc/* | tail -1 and the output is like:

xxxx is a directory 
yyyy is a directory
total 1752

My question is, how can I rid of (delete) these comments, and is there a better way to do this type of count?

1
  • 1
    I think that using find is not 100% wright, because in /etc there's not only regular files f but also links l . so this version is much better : $ sudo wc -l /etc/* 2>/dev/null | tail -1
    – Hamza
    Jan 2, 2016 at 13:43

4 Answers 4

15

You can output the error messages to /dev/null

$ wc -l /etc/* 2>/dev/null | tail -1

With this command you are only seeing the number of lines in the files that are world readable. To see the number of lines of all the files you would have to elevated the command with sudo.

$ sudo wc -l /etc/* 2>/dev/null | tail -1
0
8

Isolate files and run wc on them

What wc -l /etc/* does is that * will expand to all items inside /etc/ directory. Thus the goal is then to isolate files and perform wc on them. There are several ways to do so.

for loop with test

The test command, or more frequently abbreviated as [ can be used to find whether an item is a regular file like so:

[ -f "$FILE" ]

Thus what we can do is iterate over all items in /etc/ and run wc on them if and only if the above command returns true. Like so:

for i in /etc/*; do [ -f "$i" ] && wc -l "$i" ; done             

find

We can also use find with -maxdepth, -type , and -exec flags

find /etc/ -maxdepth 1 \( -type f -o -type l \) -exec wc -l {} +

  • -maxdepth informs find how deep in the directory structure to go; value of 1 means only the files in the directory we want.
  • -type f tells it to look for regular files, OR (represented by -o flag) for sybolic links (represented by type l ). All of that goodness is enclosed into brackets () escaped with \ so that shell interprets them as part of to find command , rather than something else.
  • -exec COMMAND {} + structure here runs whatever command we give it , + indicating to take all the found files and stuff them as command line args to the COMMAND.

To produce total we could pipe output to tail like so

$ find /etc/ -maxdepth 1 \( -type f -o -type l \) -exec wc -l {} + | tail -n 1           
[sudo] password for xieerqi: 
 11196  total

Side-note

It's easier to just use wc -l /etc/* 2>/dev/null | tail -1, as in L. D. James's answer, however find should be a part of a habit for dealing with files to avoid processing difficult filenames. For more info on that read the essay How to deal with filenames correctly

0
5

find does that easily:

sudo wc -l $(find /etc/ -maxdepth 1 -type f -iname '*')

Output:

...
828 /etc/mime.types
25 /etc/ts.conf
66 /etc/inputrc
 0 /etc/subgid-
8169 total

BUT if you just want the number as output and nothing else:

sudo wc -l $(find /etc/ -maxdepth 1 -type f -iname '*') | grep total | awk '{print $1}'

EDIT: newlines error kos said prevails. Only using -exec rectifies it. Also, /etc doesn't contain such files.

Output:

8169

As pointed by kos, the above command can be reduced to:

sudo wc -l $(find /etc/ -maxdepth 1 -type f -iname '*') | awk 'END {print $1}'

EDIT: newlines error kos said prevails. Only using -exec rectifies it. Also, /etc doesn't contain such files.

Output:

8169
2
  • 4
    What's the purpose of -iname '*'? doesn't find match everything by default? Jan 2, 2016 at 13:24
  • @steeldriver - It didn't work for me without '*'.
    – Raphael
    Jan 2, 2016 at 13:26
2

Using z-shell (zsh), the queen of the shells, instead of bash.

sudo wc -l /etc/*(.) | tail -1
0

You must log in to answer this question.

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