Calculating bytes of code I am new to Perl and I wrote this Perl script to calculate bytes of code and lines of code in a directory. I want to know if there are any improvements that can be made to it.

#!/usr/bin/perl
# codestats.pl
# A perl script to calculate the number of lines of code in a project
# and what type of lines those code are, such as comments, code, or
# newlines. This script is specific to C/C++, but it should work with any
# language that has the same commenting scheme, so it should probably work
# with java too.
#
# Henry J Schmale
# April 30, 2015

use strict;
use warnings;

my @srcext = ("*.cpp", "*.c", "*.h", "*.hpp", "*.ino", "*.cxx", "*.cc");

my $commLines = 0; # Lines that start with a comment symbol
my $bothLines = 0; # Lines that have a comment and code
my $newLines  = 0; # Lines that are just whitespace
my $codeLines = 0; # Lines of code - lines that don't fit in another space
my $totLines  = 0; # Total lines of code
my $srcBytes  = 0; # Total Number of bytes in src code
my $fCount    = 0; # Number of files read

my $files;
for($a = 0; $a &lt; scalar(@srcext); $a++){
    $files .= `find . -name "$srcext[$a]"`;
}
my @inputs = split("\n", $files);
for($a = 0; $a &lt; scalar(@inputs); $a++){
    my $prev = $totLines;
    countLines($inputs[$a]);
    printf("Read %d ln. In %s\n", $totLines - $prev, $inputs[$a]);
    $fCount++;
}
printResults();

# Count the lines in the given file
# The first param is the file to open for counting
sub countLines{
    my ($srcfile) = @_;
    open(FILE, "&lt;$srcfile") or die "Couldn't open file: $!\n";
    my @lines = &lt;FILE&gt;;
    for($b = 0; $b &lt; scalar(@lines); $b++){
        $srcBytes += length($lines[$b]);
        $totLines++;
        if($lines[$b] =~ /^\s$/){ # is only whitespace ==&gt; newLine
            $newLines++;
            next;
        }
        if(($lines[$b] =~ /^\s*\/\//) || # comments only lines
           ($lines[$b] =~ /^\s*\/\*/) ||
           ($lines[$b] =~ /^\s*\*/)){
            $commLines++;
            next;
        }
        # code + comments
        if(($lines[$b] =~ /\/\//) ||
           ($lines[$b] =~ /\/\*.*\*\//)){
            $bothLines++;
            next;
        }
        $codeLines++;
    }
    close FILE;
}

sub calcPercent{
    return ($_[0] / $_[1]) * 100.0;
}

sub printResults{
    # print out the results
    printf("Read %d Files\n", $fCount);
    printf("Average Lines Per File: %d\n", $totLines / $fCount);
    printf("Code    : %09d ln. %06.3f", $codeLines, calcPercent($codeLines, $totLines));
    print "%\n";
    printf("Comment : %09d ln. %06.3f", $commLines, calcPercent($commLines, $totLines));
    print "%\n";
    printf("Blank   : %09d ln. %06.3f", $newLines,  calcPercent($newLines,  $totLines));
    print "%\n";
    printf("Both    : %09d ln. %06.3f", $bothLines, calcPercent($bothLines, $totLines));
    print "%\n";
    printf("Total   : %09d ln.\n", $totLines);
    printf("CodeSize: %09d bytes\n", $srcBytes);
}
It's easy to write very ugly Perl code,
but this is pretty nicely written, so congrats.

Using barewords for file handles like this is discouraged:


open(FILE, "&lt;$srcfile") or die "Couldn't open file: $!\n";
my @lines = &lt;FILE&gt;;
# ...
close FILE;



The recommended way:

open(my $fh, "&lt;$srcfile") or die "Couldn't open file: $!\n";
my @lines = &lt;$fh&gt;;
# ...
close $fh;


Some simplifications are possible.
For example instead of this:


my @srcext = ("*.cpp", "*.c");



I find this way a lot easier to type:

my @srcext = qw/*.cpp *.c/;


Another, bigger simplification is in the loops.
Instead of this:


my @lines = &lt;FILE&gt;;
for($b = 0; $b &lt; scalar(@lines); $b++){
    $srcBytes += length($lines[$b]);
    $totLines++;
    if($lines[$b] =~ /^\s$/){ # is only whitespace ==&gt; newLine
        $newLines++;
        next;
    }
    if(($lines[$b] =~ /^\s*\/\//) || # comments only lines
       ($lines[$b] =~ /^\s*\/\*/) ||
       ($lines[$b] =~ /^\s*\*/)){



You can iterate using for (&lt;$fh&gt;) { ... },
and instead of $lines[$b], benefit from the auto-variable $_,
which can be omitted from $lines[$b] =~ /.../ statements,
like this:

for (&lt;$fh&gt;) {
    $srcBytes += length($_);
    $totLines++;
    if(/^\s$/){ # is only whitespace ==&gt; newLine
        $newLines++;
        next;
    }
    if(/^\s*\/\// || # comments only lines
       /^\s*\/\*/ ||
       /^\s*\*/){