amadain
amadain

Reputation: 2836

Bash while loop behaves differently dealing with multiple test conditions

I wonder if someone could explain why a while loop treats multipe test conditions differently to an if loop. I have 2 tests that i verified came out as True and False:

Bash$ test ! -n "$(find . -maxdepth 1 -name '*.xml' -print -quit)"; echo $?
0
Bash$ test ! -e "unsentData.tmp"; echo $?
1
Bash$ 

When I ANDed these 2 tests into an if statement I got an aggregate of False as expected:

Bash$ if [ ! -n "$(find . -maxdepth 1 -name '*.xml' -print -quit)" ] && [ ! -e "unsentData.tmp" ]; then echo "True"; else echo "False"; fi
False
Bash$

Now when I put the 2 tests into a while loop I expected a sleep until both conditions were met but instead I got immediately a true result.

Bash$ while [ ! -n "$(find . -maxdepth 1 -name '*.xml' -print -quit)" ] && [ ! -e "unsentData.tmp" ]; do sleep 1; done; echo -e "All files Exist\n$(ls /opt/pcf/mfe/unsentXmlToTSM/xmlConnection0_TSM/)"
All files Exist 
unsentData.tmp
Bash$

What am I missing here? I simply want to write something that waits until the 2 conditions are met before it breaks out of the loop

A

Upvotes: 0

Views: 2168

Answers (3)

Gordon Davisson
Gordon Davisson

Reputation: 125708

A while loop executes as long as ("while") its condition is true; it sounds like you want to run the loop until its condition is true. bash has an until loop which does exactly this:

until [ ! -n "$(find . -maxdepth 1 -name '*.xml' -print -quit)" ] && [ ! -e "unsentData.tmp" ]; do
    sleep 1
done
echo -e "All files Exist\n$(ls /opt/pcf/mfe/unsentXmlToTSM/xmlConnection0_TSM/)"

Or you can just negate the condition (i.e. use "while there are files left, do..." rather than "until all files are done, do..."). In this case that just means removing the negations of the individual conditions and switching the and to an or:

while [ -n "$(find . -maxdepth 1 -name '*.xml' -print -quit)" ] || [ -e "unsentData.tmp" ]; do
    sleep 1
done
echo -e "All files Exist\n$(ls /opt/pcf/mfe/unsentXmlToTSM/xmlConnection0_TSM/)"

Upvotes: 1

Mithrandir
Mithrandir

Reputation: 25337

Your assumption is worng i think. While does execute the code between do and done while (as long as) the condition holds true. Your conditions combined evaluate to false, as seen in the output of your if-statement. Thus the body of the while loop never gets executed. Try:

while ! ( [ ! -n "$(find . -maxdepth 1 -name '*.xml' -print -quit)" ] && 
          [ ! -e "unsentData.tmp" ] )  
do 
    sleep 1
done 
echo -e "All files Exist\n$(ls /opt/pcf/mfe/unsentXmlToTSM/xmlConnection0_TSM/)"

Upvotes: 3

kev
kev

Reputation: 161604

while [ ! -n "$(find . -maxdepth 1 -name '*.xml' -print -quit)" ] && [ ! -e "unsentData.tmp" ]
    do sleep 1
done

==>

while false
    do sleep 1
done

so the do sleep 1 didn't run at all.

Upvotes: 1

Related Questions