How to know how many rows of code are there for a CLI shell, not counting empty lines?

The purpose of this question is to learn how I could count the rows of code for both sh and Bash CLI shells.

Given the kernel has about 15 million rows of code, I did have a wonder on the magnitude of rows of code for these 2 programs letting me interface with the kernel.

  • 2
    You would have to download the source for the shell in question. Then you could use a tool like cloc or similar to count the lines of code in it. – Eric Renouf Nov 24 '17 at 13:39

For the latest version of bash, i.e. bash v4.4, the answer is 134576. The command I use is

find . -name '*.[ch]' | xargs grep -v '^\s*$' | wc -l

find . -name '*.[ch]' means find files that has ends with .c or .h (not counting the .def, .po files although I think it's part of source code too)

in, grep -v '^\s*$' (historical note, change form [\s*] to \s*),

  • -v prints only the lines that do not match
  • ^ means line start
  • $ means line end
  • \s means whitespaces including space, tab, linefeed

so grep -v '^[\s]*$' excludes lines have only whitespaces and wc -l counts them.

There are many sh source codes, for UNIX v6 sh(https://etsh.io/history/sh.c). There are only 860 lines.

  • [\s] means one character, either s or backslash. Grep does not use Perl regular expressions by default. For whitespace, use [[:space:]]. – Kusalananda Nov 24 '17 at 14:38
  • @Kusalananda GNU grep recognise \s by default. Using posix standardized [[:space:]] is more robust but less convenient. – frams Nov 24 '17 at 15:01
  • ggrep (GNU grep) 3.1 does not recognize \s inside [...] as anything else than the characters s or backslash. I guess you meant \s rather than [\s]. – Kusalananda Nov 24 '17 at 15:29
  • Amusingly, there actually are lines in that source tree that only contain backslashes, 29 of them, parts of macro definitions in include/shmbutil.h. And around 300 that only have whitespace. It doesn't change the final number by much though, but the pattern still doesn't do what you'd expect. – ilkkachu Nov 24 '17 at 17:41
  • Also, for some reason which I can't understand, using ^\s*$ or ^[[:space:]]*$ as the pattern seems about 10x slower than e.g. ^ *$. – ilkkachu Nov 24 '17 at 17:43

If I've understood correctly, then your friend is the command wc.

# cat example


# wc -l example
3 example

# grep -v "^$" example | wc -l

Or only with grep:

# grep -c . example

If there are multiple files. As an example with the bash sourcecode.

# wget -c https://ftp.gnu.org/gnu/bash/bash-4.4.tar.gz
# tar xfvz bash-4.4.tar.gz
# grep -R -c . bash-4.4/ | awk -F : '{sum += $2} END {print sum}'

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.