I am working on an exam practice problem in which we need to invoke a script on a file. If the exit status is non-zero, we increment the number of fails by one, else we increment the sum variable by one. Since we don't actually have this script, I just wanted to verify that what I wrote on paper is correct, assuming that the script we are calling is called compute, and args are all the file arguments.

SUM=0
NUMFAILS=0
SCRIPT=./$compute

for args in *; do
    num=$SCRIPT args
    if (($? -ne 0)); then
        NUMFAILS++
    else
        SUM=(($SUM+$num))
    fi
done
1

There are 1 best solutions below

3
On BEST ANSWER
sum=0
numfails=0

shopt -s nullglob

for args in *; do
    if num=$(./compute "$args"); then
       ((sum+=num))
    else
       ((numfails++)) 
    fi
done
  • You can use $? for testing exit status of the last command or you can test it with if directly: if command; then echo CMD OK; fi
  • You can assign output of a command to a variable while testing its exit code:
    if output=$(command); then echo CMD OK; fi
  • Do not use uppercase variables as they could collide with environment and internal shell variables
  • It is not wise to store commands in variables: BashFAQ #50
  • NUMFAILS++: you still need to use (( to evaluate the expression: ((numfails++))
  • num=$SCRIPT args: you need to use command substitution to substitute the output of a command: num=$(./script "$args")
  • args is a variable, you need to expand it with a dollar sign: "$args". Quotes are necessary to prevent word-splitting. Note that in arithmetic context, for example ((++numfails)), you don't need to use dollar sign
  • You might want to use shopt -s nullglob to skip the for loop if there are no files in your directory
  • On @CharlesDuffy's suggestion, If you are using set -e, you should use preincrement ((++numfails)) and ((sum+=num)) || true to handle cases where set -e would terminate the script when the result of either arithmetic expression is equal to 0
  • Use shellcheck