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?