0

I'm asked to write a script (using bash) that count the number of lines in files (but only C files (.h and .c) and python files (.py)) that are regrouped in a single directory. I've already tried with this code but my calculation is always wrong

let "sum = 0"
let "sum =  sum + $(wc -l $1/*.c | tail --lines=1 | tr -dc '0-9')"
let "sum =  sum + $(wc -l $1/*.h | tail --lines=1 | tr -dc '0-9')"
let "sum =  sum + $(wc -l $1/*.py | tail --lines=1 | tr -dc '0-9')"
echo $sum >> manifest.txt

I must write the total in the "manifest.txt" file and the argument of my script is the path to the directory that contains the files.

If someone has another technique to compute this, I'd be very grateful. Thank you !

martineau
  • 119,623
  • 25
  • 170
  • 301
  • 4
    Check your script with http://shellcheck.net . `but my calculation is always wrong` in what way is it wrong? – KamilCuk Jul 23 '21 at 16:59

4 Answers4

0

Version 1: step by step

#!/bin/bash
echo "Counting the total number of lines for all .c .h .py files in $1"
sum=0
num_py=$(wc -l $1/*.py | tail -1 | tr -dc '0-9')
num_c=$(wc -l $1/*.c | tail -1 | tr -dc '0-9')
num_h=$(wc -l $1/*.h | tail -1 | tr -dc '0-9')
sum=$(($num_py + $num_c + $num_h))
echo $sum >> manifest.txt

version 2: concise

#!/bin/bash
echo "Counting the total number of lines for all .c .h .py files in $1"
echo "$(( $(wc -l $1/*.py | tail -1 | tr -dc '0-9') + $(wc -l $1/*.c | tail -1 | tr -dc '0-9') + $(wc -l $1/*.h | tail -1 | tr -dc '0-9') ))" >> manifest.txt

version 3: loop over your desired files

#!/bin/bash
echo "Counting the total number of lines for all .c .h .py files in $1"
sum=0
for sfile in $1/*.{c,h,py}; do 
sum=$(($sum+$(wc -l $sfile|tail -1|tr -dc '0-9')))
done
echo $sum >> manifest.txt

This is how arithmetic operations work: var = $((EXPR)) For example: $sum= $(($sum + $result )) it is very common to miss the $ sign within the EXPR! Try not to forget them :)

Farid
  • 1
  • 2
0

You could also use a loop to aggregate the counts:

extensions=("*.h" "*.c" "*.py")

sum=0
for ext in ${extensions[@]} ; do
   count=$(wc -l ${1}/${ext} | awk '{ print $1 }')
   sum=$((sum+count))
done    

echo "${sum}"
j_b
  • 1,975
  • 3
  • 8
  • 14
0

This is the scripts that I use (with minor modifications):

files=( $(find . -mindepth 1 -maxdepth 1 -type f -iname "*.h" -iname "*.c" -iname "*.py") )
declare -i total=0

for file in "${files[@]}"; do
    lines="$(wc -l < <(cat "$file"))"
    echo -e "${lines}\t${file}"
    total+="$lines"
done

echo -e "\n$total\ttotal"

nino
  • 554
  • 2
  • 7
  • 20
0

Here is my version.

#!/usr/bin/env bash

shopt -s extglob nullglob

files=( "$1"/*.@(c|h|py) )

shopt -u extglob nullglob

while IFS= read -rd '' file_name; do
  count=$(wc -l < "$file_name")
  ((sum+=count))
done< <(printf '%s\0' "${files[@]}")

echo "$sum" > manifest.txt

Needs some error checking, like if the argument is a directory or if it even exists at all, and so on.

Jetchisel
  • 7,493
  • 2
  • 19
  • 18