简体   繁体   中英

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

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/)"
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.

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 (ie 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/)"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM