Bash script: do something one time inside a loop then stop, but continue looping
push(){
shuttle push note Chrome \
"Aurora: $1" \
"Battery is at $percent percent"
}
full=0
while percent=$(acpi | awk '{ print $4}' | sed 's/[,%]//g')
do case $percent:$full in
(100:1) ;; (100:0)
full=1
push 'Battery charged';;
(?:*|1?:*|20:*)
full=0
push 'Plug in Now';;
(*1) full=0
esac
done
The shell's case
statement allows you to execute an arbitrary code block based on whether or not a shell pattern can be matched against the value of a shell expansion. In this way you can very simply handle multiple possible outcomes of the very same test.
Above I concatenate the values of $percent
and $full
on a :
colon delimiter, which is a technique I originally picked up from Stephane Chazelas even if I have become fairly good with it on my own right since. Because the code executed needs to depend on both values, testing both simultaneously is the most simple solution.
case
pattern blocks are evaluated in order from first to last. As soon as a pattern is matched the associated code is executed and case
returns. The first matched pattern is also the last pattern evaluated.
And so if the values of $percent
and $full
are respectively:
100 and 1
- The first pattern is matched, which is associated with an empty code block. No action is taken, and
case
returns towhile
.
- The first pattern is matched, which is associated with an empty code block. No action is taken, and
100 and 0
- The second pattern is matched, which sets
$full
to 1 and calls the shell functionpush
w/ the argumentBattery Charged
push()
is only defined here to organize the code according to purpose.
- The second pattern is matched, which sets
<=20 and anything at all
- The third pattern is matched,
$full
is set to 0, andpush
is called with the argPlug in Now
.
- The third pattern is matched,
anything at all and 1
- The last pattern is matched and
$full
is set to 0.
- The last pattern is matched and
Anything else
- No pattern is matched and no action is taken.
Taken altogether, this means that $full
is only set when necessary, push()
is only called when $full
is 0 and $percent
is 100 or $full
is anything and $percent
is <=20.
All of that would be something of an improvement on what you have already. But the real problem there is:
percent=$(acpi | awk '{ print $4}' | sed 's/[,%]//g')
Forking multiple times like that in a while true
is incredibly wasteful. You've gotta come up with another way to do that.
How about:
if [ "$percent" -eq 100 ] && [ "$full_flag" -eq 0 ];
then
shuttle push note Chrome "Aurora: Battery charged" "Battery is at $percent percent"
full_flag=1
fi
if [ "$percent" -lt 100 ];
then
full_flag=0
fi