1

Still getting the hang of bash scripting...

I have a function that resizes images and calculates how much to scale it based on the file size. I need to pass this percentage as an argument to the convert command, but I can't remove the return from the end of the string.

When I run the function, I get:

2.362413
%

How can I concatenate these on one line without a return or newline char? Piping to tr with '\r' or '\d' doesn't seem to work.

 shrinkImg() {
   FILENAME=$(basename "$1")
   EXTENSION="${FILENAME##*.}"
   sz=$(stat -c '%s' $1)
   PRODUCT=echo bc <<< "scale = 10; ( 100 / ( $sz / 350000))"; 
   PRODUCT=echo ${PRODUCT} | tr -d '\r'
   PERCENT=%
   TARGET=echo $TARGET
   TARGET=$PRODUCT$PERCENT
   echo $TARGET;
   if [ $sz -ge 350000 ] && [ $EXTENSION == 'png' ] ; then
     convert $1 -resize $TARGET $1
   elif [ $sz -ge 350000 ] && [ $EXTENSION == 'PNG' ] ; then
     convert $1 -resize $TARGET $1 
   elif [ $sz -ge 350000 ] && [ $EXTENSION == 'jpg' ] ; then
     convert $1 -resize $TARGET $1
   elif [ $sz -ge 350000 ] && [ $EXTENSION == 'JPG' ] ; then
     convert $1 -resize $TARGET $1
   fi
 }

Also any other tips would be appreciated!

2
  • Why use 100 / ( $sz / 350000)? What's wrong with 35000000 / $sz? (Unless of course you want the additional rounding errors introduced by the first formula: try both with sz=1000000.) You should be aware that the conversion you are applying will reduce the file size by a lot more than you may intend (maybe 100*sqrt(350000/$sz) is better?). It's worth mentioning that if you are happy with rounding to the nearest integer percent you can use $((35000000/$sz)) without using an external program. Note also that the filter to remove new-lines is tr -d '\n', not tr -d '\r'.
    – AFH
    May 23, 2016 at 16:40
  • @AFH , You're right, that's much better. Thank you!
    – ddmd
    May 23, 2016 at 20:50

2 Answers 2

0

There are several weird lines in the code.

For example:

PRODUCT=echo ${PRODUCT} | tr -d '\r'

This assigns the string "echo" into $PRODUCT, and runs ${PRODUCT} | tr -d '\r' with the previous value of $PRODUCT.

What you need is command substitution:

filename=${1##*/}
extension=${filename##*.}
sz=$(stat -c %s "$1")
product=$(bc <<< "scale = 10; ( 100 / ( $sz / 350000))")
echo $product%
0

I took a different approach to improvement... No piping to tr, and just making the '%" part of the output. Then since all the if elsif statements were complex, yet performing the same commands, I simplified them into one case statement.

shrinkImg() {
   FILENAME=$(basename "$1")
   EXTENSION="${FILENAME##*.}"
   sz=$(stat -c '%s' $1)
   TARGET=$(echo 35000000 | awk '{print $1/'$sz')"%"}')
   echo $TARGET
   if [ $sz -ge 350000 ]; then
      case $EXTENSION in
         png|PNG|jpg|JPG) convert $1 -resize $TARGET $1;;
         *) echo "Unexpected extension, $EXTENSION";;
      esac
   fi
}

The TARGET variable is a bit more confusing now, but I wanted to demonstrate an alternative to your bc command. Awk does math, and can format output too.

To break it down, awk is is passed the constant value of 35000000 (this number was 350000, but I multiplied by 100 to convert decimal to percent) and tracks this field/value as "$1". Since $sz is not defined or set from inside of awk itself, we break out of the awk by closing the single quote and reaching into the previous level of the the function to get the value of $sz. Then we end that call out by starting our single quotes again. With all the math organized, we print the result including an appended a percent sign.

Without the percent sign, the decimal has to move again.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .