I'm a HPC guy so I'm all about "make it work, then make it fast." I have a little bash script which gets a Physical Source Lines Of Code (PSLOC) and Logical SLOC (currently just of Java code, but it would work for C and C++ too). It works by finding all *.java
files in a directory and then goes through each file found and uses sed to delete stuff I don't want. It first does PSLOC by deleting all comments, whitespace, and blank lines. It then gets LSLOC by taking PSLOC and deleting all lines starting with #
or @
, replacing {}()
's with a blank space, deleting whitespace, and finally deleting blank lines. I get the line count for PSLOC and LSLOC with wc -l
.
This works, but I'm a scripting noob and haven't done anything like this before. What I'm wondering is how can I make this script faster and easier to read/maintain:
#!/bin/bash
DIR="C:/dev/somejavafolder"
LANGUAGE="java"
find "$DIR" -type f -name "*.$LANGUAGE" > filelist
while read FILE; do
PSLOC="$FILE.psloc"
LSLOC="$FILE.lsloc"
# Get PSLOC
sed -e "s/\/\/.*$//" $FILE > $PSLOC # deletes all /* to */ lines
sed -i -e 's|/\*|\n&|g;s|*/|&\n|g' $PSLOC # ^
sed -i -e '/\/\*/,/*\//d' $PSLOC # deletes all // lines
sed -i -e 's/^[ \t]*//' -e 's/[ \t]*$//' $PSLOC # deletes all whitespace
sed -i -e '/^$/d' $PSLOC # deletes all blank lines
wc -l $PSLOC
# Get LSLOC
sed -e 's/#.*//' $PSLOC > $LSLOC # deletes all # lines
sed -i -e 's/@.*//' $LSLOC # deletes all # lines
sed -i -e 's/{/ /g;s/}/ /g;s/)/ /g;s/(/ /g' $LSLOC # replaces {}() with spaces
sed -i -e 's/^[ \t]*//' -e 's/[ \t]*$//' $LSLOC # deletes all whitespace
sed -i -e '/^$/d' $LSLOC # deletes all blank lines
wc -l $LSLOC
done < filelist
find "$DIR" -name "*.*sloc" -type f -delete
This gets PSLOC and LSLOC counts of 531 java files (~80524 lines) in about 4 minutes.
Edit: per @choroba's suggestion, I changed the file to
#!/bin/bash
DIR="C:/dev/somejavafolder"
LANGUAGE="java"
find "$DIR" -type f -name "*.$LANGUAGE" > filelist
while read FILE; do
PSLOC="$FILE.psloc"
LSLOC="$FILE.lsloc"
sed -e "s/\/\/.*$//" -e 's|/\*|\n&|g;s|*/|&\n|g' -e '/\/\*/,/*\//d' -e 's/^[ \t]*//' -e 's/[ \t]*$//' -e '/^$/d' $FILE > $PSLOC # deletes all /* to */ lines
wc -l $PSLOC
sed -e 's/#.*//' -e 's/@.*//' -e 's/{/ /g;s/}/ /g;s/)/ /g;s/(/ /g' -e 's/^[ \t]*//' -e 's/[ \t]*$//' -e '/^$/d' $PSLOC > $LSLOC # deletes all # lines
wc -l $LSLOC
done < filelist
find "$DIR" -name "*.*sloc" -type f -delete
and the runtime went down to about 80 seconds. Awesome! Any other ideas?