Reputation: 11936
I have a script and want to ask the user for some information, but the script cannot continue until the user fills in this information. The following is my attempt at putting a command into a loop to achieve this but it doesn't work for some reason:
echo "Please change password"
while passwd
do
echo "Try again"
done
I have tried many variations of the while loop:
while `passwd`
while [[ "`passwd`" -gt 0 ]]
while [ `passwd` -ne 0 ]]
# ... And much more
But I can't seem to get it to work.
Upvotes: 366
Views: 237848
Reputation: 1763
I prefer for-loop (with a large number) over while-loop. My solution is to use for-loop with bash
and Here document. For example,
#!/bin/bash
set -e
for count in $(seq 1 5000); do bash <<EOF && break
echo "try $count ..."
false
EOF
done && echo ok || echo err
It's easy to extend this method to run command remotely or inside a container, for example,
#!/bin/bash
set -e
for count in $(seq 1 5000); do ssh remote-host bash <<EOF && break
echo "try $count ..."
hostname && false
EOF
done && echo ok || echo err
Upvotes: 0
Reputation: 1275
It becomes a little tricky if you want the strict mode (set -e
) and none of above worked.
set -euo pipefail
counter=0
max_attempts=3
while ret=0; <your command> || ret=$?; [ $ret -ne 0 ]
do
[[ $counter -eq $max_attempts ]] && echo "Command failed"; exit 1
sleep 2
echo "Trying again"
counter=$((counter+1))
done
Upvotes: 1
Reputation: 15207
To elaborate on @Marc B's answer,
$ passwd
$ while [ $? -ne 0 ]; do !!; done
Is a nice way of doing the same thing that's not command specific.
If you want to do this as an alias (kudos to @Cyberwiz):
alias rr='while [ $? -ne 0 ]; do eval $(history -p !!); done'
Usage:
$ passwd
$ rr
Upvotes: 132
Reputation: 3877
If anyone looking to have retry limit:
max_retry=5
counter=0
until <YOUR_COMMAND>
do
sleep 1
[[ counter -eq $max_retry ]] && echo "Failed!" && exit 1
echo "Trying again. Try #$counter"
((counter++))
done
Upvotes: 34
Reputation: 91270
until passwd
do
echo "Try again"
done
or
while ! passwd
do
echo "Try again"
done
Upvotes: 577
Reputation: 25599
You can use an infinite loop to achieve this:
while true
do
read -p "Enter password" passwd
case "$passwd" in
<some good condition> ) break;;
esac
done
Upvotes: 10
Reputation: 360612
You need to test $?
instead, which is the exit status of the previous command. passwd
exits with 0 if everything worked ok, and non-zero if the passwd change failed (wrong password, password mismatch, etc...)
passwd
while [ $? -ne 0 ]; do
passwd
done
With your backtick version, you're comparing passwd's output, which would be stuff like Enter password
and confirm password
and the like.
Upvotes: 117