Bash script to get total size off of remainder calculated

I am working on a script to get the final total size and so far have the following and wondering if this can be improved.

# Compare the desired size of each lvm to the standard size. If it is desired is larger than calculate the difference and keep that value as the amount to add to that LVM.
# If the desired size is smaller than the standard than set the amount to add as 0.

If VarSize > VarStandard Then
VarAdd = VarSize - VarStandard
Else
VarAdd = 0
End If
 
If OptSize > OptStandard Then
OptAdd = OptSize - OptStandard
Else
OptAdd = 0
End If
 
If HomeSize > HomeStandard Then
HomeAdd = HomeSize - HomeStandard
Else
HomeAdd = 0
End If
 
If TmpSize > VarStandard Then
TmpAdd = TmpSize - TmpStandard
Else
TmpAdd = 0
End If
 
 
# Add up the additional amount required for each LVM to get the total additional required space
TotalAdd = VarAdd + OptAdd + HomeAdd + TmpAdd

My script flow for this:

#!/bin/bash
"$1"=5
"$2"=3
"$3"=2
"$4"=2

VarStandard=4
OptStandard=2
HomeStandard=1
TmpStandard=1

if (( $( echo "$1 > $VarStandard" |bc))); then
    VarAdd=$( $1 % $VarStandard ) 
      fi
  if (( $( echo "$1 > $OptStandard" |bc))); then
    OptAdd=$( $2 % $OptStandard ) 
  fi
  if (( $( echo "$3 > $HomeStandard" |bc))); then
    HomeAdd=$( $3 % $HomeStandard ) 
  fi
  if (( $( echo "$4 > $TmpStandard" |bc))); then
    TmpAdd=$( $4 % $TmpStandard ) 
  fi
  
if [ $(( VarAdd + OptAdd + HomeAdd + TmpAdd )) -eq 0 ] ; then
   echo "No Space needed"
  else
   echo "$(( VarAdd + OptAdd + HomeAdd + TmpAdd )) extra space is needed"
   fi

Few simple modifications:

[highlight=bash]
#!/bin/bash

VarSize=${1-5} # use $1 if defined, else set VarSize as 5
OptSize=${2-3} # use $2 if defined, else set OptSize as 3
HomeSize=${3-2} # use $3 if defined, else set HomeSize as 2
TmpSize=${4-2} # use $4 if defined, else set TmpSize as 2

# Here you may have extra code to check if all the above variables are numbers and not something else.
# Left as an exercise to the OP.

VarStandard=4
OptStandard=2
HomeStandard=1
TmpStandard=1

if (( VarSize > VarStandard )); then # Why pipe it to bc when bash has provision to perform math
VarAdd=$(( VarSize - VarStandard ))
fi
if (( OptSize > OptStandard )); then
OptAdd=$(( OptSize - OptStandard ))
fi
if (( HomeSize > HomeStandard )); then
HomeAdd=$(( HomeSize - HomeStandard ))
fi
if (( TmpSize > TmpStandard )); then
TmpAdd=$(( TmpSize - TmpStandard ))
fi

if (( $(( VarAdd + OptAdd + HomeAdd + TmpAdd )) == 0 )) ; then
echo "No Space needed"
else
echo "$(( VarAdd + OptAdd + HomeAdd + TmpAdd )) extra space is needed"
fi

[/highlight]

2 Likes

Thanks for the response. This is one of the pieces for my final script which I am building. The script's intended use is ./scriptname arg 1 arg2 arg3 arg4 from the command line. The arguments will get passed to the default bash variables ( $1 $2 $3 $4 etc.) hence I was using them in my statements. The use of bc is to future proof it if numbers are not integers but floating numbers.

It would have been very helpful if you had told us what errors you were getting, how you expected to invoke your script, and that you wanted to be able to perform floating point arithmetic up front instead of asking us to waste our time guessing at what you might be trying to do. Please don't assume that we can always figure out what you're trying to do by looking at code that won't work. Most of us don't have a crystal ball that works that well. :frowning:

Have you considered using ksh instead of bash ? A 1993 or later version of the Korn shell handles floating point values in addition to handling integers (although I'm not sure it will accept floating point values as the right hand operand in a mod operation). You haven't said anything about the range or precision of the numbers you expect to encounter. The bc utility can handle arbitrary precision (if you tell it what precision you want, which your bc scripts do not do) while ksh will limit you to double-precision floating point arithmetic.

Note also that if you have floating point values for any of your operands, you can't use bash arithmetic expansions to perform arithmetic (even after using bc to compare numbers). You'll get syntax error from bash if any of the operands in an arithmetic expansion aren't integers.

And, statements in your original code like:

    VarAdd=$( $1 % $VarStandard ) 

are not arithmetic expansions; they are command substitutions. That statement attempts to execute the utility named by whatever $1 expands to with the two operands % and 4 (which is what $VarStandard expands to in your sample script) and assign the output written to standard output by that utility to the shell variable named VarAdd . Arithmetic expansions are of the form:

$((expression))

(note the double parentheses instead of single parentheses).

If you really need arbitrary precision floating point arithmetic to perform all of these calculations, have you considered writing all of those calculations as a single bc script so you only have to invoke bc once instead of ten times?

How about, then, making efficient use of bc and bash ? Try

read VAdd OAdd HAdd TAdd <<< $(bc <<< "print $1 - $VarStandard, \" \", $2 - $OptStandard, \" \", $3 - $HomeStandard, \" \", $4 - $TmpStandard")
Delta="$(( (VAdd>0?VAdd:0) + (OAdd>0?OAdd:0) + (HAdd>0?HAdd:0) + (TAdd>0?TAdd:0) ))"
if  [ $Delta -eq 0 ]
  then  echo "No space needed"
  else  echo "$Delta extra space is needed"
fi

Thanks to balajesuri, Don Cragun and RudiC for taking the time to respond to this thread.

Balajesuri - I will play further with the code and report back if any issues.
Don, I can only use Bash but I will go over your post and try to incorporate the suggestions.
RudiC, Thanks for the suggestion, I'll test it out.