I was working on a tcsh
script that did some cool stuff. But if a
user ran that script not knowing the true impact of the script, it
could make some bad irreversible changes.
While I could simply echo a warning statement and put a sleep 10
, I
wanted the wait time to be shown live.
So here’s what worked pretty nicely — The warning message is shown to the user, and the actual wait time countdown is also displayed.
#!/usr/bin/env tcsh
set wait_time = 10 # seconds
echo "Are you sure you meant to run this script?"
echo "This script does something drastic that you would severely regret if you happened to run this script by mistake!"
echo ""
set temp_cnt = ${wait_time}
# https://www.cyberciti.biz/faq/csh-shell-scripting-loop-example/
while ( ${temp_cnt} >= 1 )
printf "\rYou have %2d second(s) remaining to hit Ctrl+C to cancel that operation!" ${temp_cnt}
sleep 1
@ temp_cnt--
end
echo ""
while
loop runs for $wait_time
times; each time waiting for
a second (sleep 1
) and then decrementing the temporary counter
$temp_cnt
.printf
is chosen instead of echo -n
because I wanted to have the
seconds number always hold 2 character places (%2d
).\r
character in printf
makes the magic here. It represents
carriage return i.e. The cursor will return to the beginning of
the line, and then print the following string, overwriting
whatever there was on that line earlier.
printf
acts like echo -n
i.e. a newline is not inserted
automatically at the end of the printed message. In order to add a
newline at the end for printf
, you need to do so explicitly by
adding a \n
character.Click here to see the animation on asciinema.org.
Below is a re-implementation of the above in bash.
#!/usr/bin/env bash
wait_time=10 # seconds
echo "Are you sure you meant to run this script?"
echo "This script does something drastic that you would severely regret if you happened to run this script by mistake!"
echo ""
temp_cnt=${wait_time}
while [[ ${temp_cnt} -gt 0 ]];
do
printf "\rYou have %2d second(s) remaining to hit Ctrl+C to cancel that operation!" ${temp_cnt}
sleep 1
((temp_cnt--))
done
echo ""