This question already has an answer here:
I am having a hard time tracking down the reason my 'boolean' flag variable won't stay false when a test fails inside a while loop.
The script involves a few loops but essentially it is intended to play two random albums every morning when it is triggered by cron. I used to have a simple one-liner script that selected two albums but I wanted to blacklist any albums that I didn't want playing (i.e. christmas music albums).
To do this, I had it read a wakeUp_blacklist.txt file with the names of albums I didn't want to hear so it can reject any matches. This compares the blacklisted albums line-by-line with one randomly selected album and tests for a match. If a match is found, it flags the match as a failure (
pass = false) and SHOULD loop back and select a different album. For some reason, as soon as the execution exits the
read | while loop, the flag switches back to true and so another album is never selected!
Here is my code and an example output:
#!/bin/bash wd="/media/External1/albums" pass="false" for ((i=0; i<=1; i++)); do while [ "$pass" == "false" ]; do album=`ls -d "$wd"/*/*/ | sort -R | tail -n 1` echo "album selected:" echo "$album" pass="true" echo "pass reset; pass=$pass" cat "$wd/wakeUp_blacklist.txt" | while read black; do echo "pass check 2:$pass" echo "black: $wd/$black" if [ "$album" == "$wd/$black" ] || [ "$album\n" == "$albums" ]; then pass="false" echo "test failed; pass=$pass" fi echo "pass check 1:$pass" done echo "Blacklist check complete; pass=$pass" #Why is it true again?! done pass="false" albums="$albums$album\n" echo "album assigned:" echo "$album" done echo echo for album in "$albums"; do # play "$album*" echo -e "$album" #List album names rather than actually play them done
So, if I run this a few times, it will eventually chose one of the blacklisted albums and give output that looks like:
album selected: /media/External1/albums/Adele/21/ pass reset; pass=true pass check 2:true black: /media/External1/albums/Vince_Guaraldi_Trio/A_Charlie_Brown_Christmas/ pass check 1:true pass check 2:true black: /media/External1/albums/Sound_Inventions/Stille_Nacht-_A_German_Christmas/ pass check 1:true Blacklist check complete; pass=true album assigned: /media/External1/albums/Adele/21/ album selected: /media/External1/albums/Sound_Inventions/Stille_Nacht-_A_German_Christmas/ pass reset; pass=true pass check 2:true black: /media/External1/albums/Vince_Guaraldi_Trio/A_Charlie_Brown_Christmas/ pass check 1:true pass check 2:true black: /media/External1/albums/Sound_Inventions/Stille_Nacht-_A_German_Christmas/ test failed; pass=false pass check 1:false Blacklist check complete; pass=true album assigned: /media/External1/albums/Sound_Inventions/Stille_Nacht-_A_German_Christmas/ /media/External1/albums/Adele/21/ /media/External1/albums/Sound_Inventions/Stille_Nacht-_A_German_Christmas/
You can see that towards the end, when the blacklist entry is a match for the selected album (German_Christmas) the test fails, the
pass variable is
false but the first output that checks
pass value outside the
read | while loop shows it being true again!
I understand that my script may not be as efficient as possible yet but I want to understand what is happening here before I move on. Any suggestions?