You're giving sleep
two arguments, 3
and $(( i++ ))
. With GNU tools, this means that the loop would sleep an increasing number of seconds in each iteration. On a non-GNU system, you would get an error from sleep
.
Your loop will always run at least 10 times due to the way you have written your test. Your test says "Iterate while $i
is less or equal to 10". Once $i
reaches 10, the other part of the test will come into effect. You probably want a logical AND test here rather than an OR.
You should not use ls | wc -l
to count files in a directory. This will give the wrong result in some (albeit pathological) cases.
Instead:
i=1
while [ "$i" -ne 10 ]; do
set -- /opt/hosts/*
if [ "$#" -ge 2 ]; then
break
fi
sleep 3 # or, to sleep longer and longer: sleep "$(( 3 + i ))"
i=$(( i + 1 ))
done
This properly increments i
in each iteration, and also uses a safer way to count the number of names in the /opt/hosts
directory (by expanding the *
glob in the directory and counting the number of names that it expands to). The loop exits whenever the number of names is two or more, or whenever $i
reaches the value 10.
After the loop, if $i
is 10, then the files failed to materialize.
If you need to preserve your positional parameters (these would be overwritten by the set
command), then expand the glob into an array with names=( /opt/hosts/* )
and then use "${#names[@]}"
to get the length of that array instead of using "$#"
.
You could also write it as
i=1
while [ "$i" -ne 10 ] && ( set -- /opt/hosts/*; [ "$#" -lt 2 ] )
do
sleep 3
i=$(( i + 1 ))
done
This would not clobber your existing positional parameters as set
is running in a subshell. It would also be closer to the type of thing you attempted yourself.
As a "one-liner":
i=1; while [ "$i" -ne 10 ]; do set -- /opt/hosts/*; [ "$#" -ge 2 ] && break; sleep 3; i=$(( i + 1 )); done
Or, with an "arithmetic for
loop" in bash
:
for (( i=1; i<=10; i++ )); do set -- /opt/hosts/*; [ "$#" -ge 2 ] && break; sleep 3; done
Or, with that last piece of code above the divider:
i=1; while [ "$i" -ne 10 ] && ( set -- /opt/hosts/*; [ "$#" -lt 2 ] ); do sleep 3; i=$(( i + 1 )); done