Jonathan Hartley
Jonathan Hartley

Reputation: 16034

count (non-blank) lines-of-code in bash

In Bash, how do I count the number of non-blank lines of code in a project?

Upvotes: 182

Views: 162101

Answers (21)

Jaydillan
Jaydillan

Reputation: 161

Solution
cat file.txt | awk 'NF' | wc -l
Explanation

'NF' evaluates to true if the number of fields (NF) in a line is non-zero. By default, awk interprets each line of input as records and breaks them into fields based on whitespace. So, 'NF' evaluates to true for lines that are not empty. As a result, this command filters out empty lines from the input.

Upvotes: 16

user3342816
user3342816

Reputation: 1263

Using Perl:

perl -ne '!/^\s*$/ && ++$i; eof && printf "%d\n", $i'
# or
perl -ne '++$i if not /^\s*$/; printf "%d\n", $i if eof'
# or
perl -ne '++$i if ! /^\s*$/; printf "%d\n", $i if eof'
# ...

Where /PATTERN/ is anything one want to skip.

Using bash:

while IFS= read -r n; do 
    ! [[ "$n" =~ ^\s*# ]] && ((++i))
done
printf '%d\n' $i

Upvotes: 0

Hamza Awashra
Hamza Awashra

Reputation: 25

Try this one:

> grep -cve ^$ -cve '^//' *.java

it's easy to memorize and it also excludes blank lines and commented lines.

Upvotes: 0

Son Nguyen
Son Nguyen

Reputation: 315

The neatest command is

grep -vc ^$ fileName

with -c option, you don't even need wc -l

Upvotes: 2

coastline
coastline

Reputation: 1802

This command count number of non-blank lines.
cat fileName | grep -v ^$ | wc -l
grep -v ^$ regular expression function is ignore blank lines.

Upvotes: 25

jean-emmanuel
jean-emmanuel

Reputation: 29

rgrep . | wc -l

gives the count of non blank lines in the current working directory.

Upvotes: 2

mahesh
mahesh

Reputation: 17

This gives the count of number of lines without counting the blank lines:

grep -v ^$ filename wc -l | sed -e 's/ //g' 

Upvotes: 0

curran
curran

Reputation: 1316

Here's a Bash script that counts the lines of code in a project. It traverses a source tree recursively, and it excludes blank lines and single line comments that use "//".

# $excluded is a regex for paths to exclude from line counting
excluded="spec\|node_modules\|README\|lib\|docs\|csv\|XLS\|json\|png"

countLines(){
  # $total is the total lines of code counted
  total=0
  # -mindepth exclues the current directory (".")
  for file in `find . -mindepth 1 -name "*.*" |grep -v "$excluded"`; do
    # First sed: only count lines of code that are not commented with //
    # Second sed: don't count blank lines
    # $numLines is the lines of code
    numLines=`cat $file | sed '/\/\//d' | sed '/^\s*$/d' | wc -l`

    # To exclude only blank lines and count comment lines, uncomment this:
    #numLines=`cat $file | sed '/^\s*$/d' | wc -l`

    total=$(($total + $numLines))
    echo "  " $numLines $file
  done
  echo "  " $total in total
}

echo Source code files:
countLines
echo Unit tests:
cd spec
countLines

Here's what the output looks like for my project:

Source code files:
   2 ./buildDocs.sh
   24 ./countLines.sh
   15 ./css/dashboard.css
   53 ./data/un_population/provenance/preprocess.js
   19 ./index.html
   5 ./server/server.js
   2 ./server/startServer.sh
   24 ./SpecRunner.html
   34 ./src/computeLayout.js
   60 ./src/configDiff.js
   18 ./src/dashboardMirror.js
   37 ./src/dashboardScaffold.js
   14 ./src/data.js
   68 ./src/dummyVis.js
   27 ./src/layout.js
   28 ./src/links.js
   5 ./src/main.js
   52 ./src/processActions.js
   86 ./src/timeline.js
   73 ./src/udc.js
   18 ./src/wire.js
   664 in total
Unit tests:
   230 ./ComputeLayoutSpec.js
   134 ./ConfigDiffSpec.js
   134 ./ProcessActionsSpec.js
   84 ./UDCSpec.js
   149 ./WireSpec.js
   731 in total

Enjoy! --Curran

Upvotes: 3

sami
sami

Reputation: 51

grep -cvE '(^\s*[/*])|(^\s*$)' foo

-c = count
-v = exclude
-E = extended regex
'(comment lines) OR (empty lines)'
where
^    = beginning of the line
\s   = whitespace
*    = any number of previous characters or none
[/*] = either / or *
|    = OR
$    = end of the line

I post this becaus other options gave wrong answers for me. This worked with my java source, where comment lines start with / or * (i use * on every line in multi-line comment).

Upvotes: 5

G1i1ch
G1i1ch

Reputation: 251

There's already a program for this on linux called 'wc'.

Just

wc -l *.c 

and it gives you the total lines and the lines for each file.

Upvotes: -3

Jonathan Hartley
Jonathan Hartley

Reputation: 16034

'wc' counts lines, words, chars, so to count all lines (including blank ones) use:

wc *.py

To filter out the blank lines, you can use grep:

grep -v '^\s*$' *.py | wc

'-v' tells grep to output all lines except those that match '^' is the start of a line '\s*' is zero or more whitespace characters '$' is the end of a line *.py is my example for all the files you wish to count (all python files in current dir) pipe output to wc. Off you go.

I'm answering my own (genuine) question. Couldn't find an stackoverflow entry that covered this.

Upvotes: 14

Andy
Andy

Reputation: 81

If you want the sum of all non-blank lines for all files of a given file extension throughout a project:

while read line
do grep -cve '^\s*$' "$line"
done <  <(find $1 -name "*.$2" -print) | awk '{s+=$1} END {print s}'

First arg is the project's base directory, second is the file extension. Sample usage:

./scriptname ~/Dropbox/project/src java

It's little more than a collection of previous solutions.

Upvotes: 1

Keith Pinson
Keith Pinson

Reputation: 7985

Script to recursively count all non-blank lines with a certain file extension in the current directory:

#!/usr/bin/env bash
(
echo 0;
for ext in "$@"; do
    for i in $(find . -name "*$ext"); do
        sed '/^\s*$/d' $i | wc -l ## skip blank lines
        #cat $i | wc -l; ## count all lines
        echo +;
    done
done
echo p q;
) | dc;

Sample usage:

./countlines.sh .py .java .html

Upvotes: 1

Dutch
Dutch

Reputation: 9

grep -v '^\W*$' `find -type f` | grep -c '.' > /path/to/lineCountFile.txt

gives an aggregate count for all files in the current directory and its subdirectories.

HTH!

Upvotes: 0

SpoonMeiser
SpoonMeiser

Reputation: 20397

There are many ways to do this, using common shell utilities.

My solution is:

grep -cve '^\s*$' <file>

This searches for lines in <file> the do not match (-v) lines that match the pattern (-e) '^\s*$', which is the beginning of a line, followed by 0 or more whitespace characters, followed by the end of a line (ie. no content other then whitespace), and display a count of matching lines (-c) instead of the matching lines themselves.

An advantage of this method over methods that involve piping into wc, is that you can specify multiple files and get a separate count for each file:

$ grep -cve '^\s*$' *.hh

config.hh:36
exceptions.hh:48
layer.hh:52
main.hh:39

Upvotes: 42

Michael Cramer
Michael Cramer

Reputation: 5230

cat foo.c | sed '/^\s*$/d' | wc -l

And if you consider comments blank lines:

cat foo.pl | sed '/^\s*#/d;/^\s*$/d' | wc -l

Although, that's language dependent.

Upvotes: 222

Gilles
Gilles

Reputation: 7339

#!/bin/bash
find . -path './pma' -prune -o -path './blog' -prune -o -path './punbb' -prune -o -path './js/3rdparty' -prune -o -print | egrep '\.php|\.as|\.sql|\.css|\.js' | grep -v '\.svn' | xargs cat | sed '/^\s*$/d' | wc -l

The above will give you the total count of lines of code (blank lines removed) for a project (current folder and all subfolders recursively).

In the above "./blog" "./punbb" "./js/3rdparty" and "./pma" are folders I blacklist as I didn't write the code in them. Also .php, .as, .sql, .css, .js are the extensions of the files being looked at. Any files with a different extension are ignored.

Upvotes: 55

Linor
Linor

Reputation: 1860

It's kinda going to depend on the number of files you have in the project. In theory you could use

grep -c '.' <list of files>

Where you can fill the list of files by using the find utility.

grep -c '.' `find -type f`

Would give you a line count per file.

Upvotes: 1

curtisk
curtisk

Reputation: 20175

cat 'filename' | grep '[^ ]' | wc -l

should do the trick just fine

Upvotes: 6

xsl
xsl

Reputation: 17406

If you want to use something other than a shell script, try CLOC:

cloc counts blank lines, comment lines, and physical lines of source code in many programming languages. It is written entirely in Perl with no dependencies outside the standard distribution of Perl v5.6 and higher (code from some external modules is embedded within cloc) and so is quite portable.

Upvotes: 40

Ben Hoffstein
Ben Hoffstein

Reputation: 103325

awk '/^[[:space:]]*$/ {++x} END {print x}' "$testfile"

Upvotes: 4

Related Questions