Reputation: 181
Not sure if it's possible but I'm trying to break out of an if
statement that's in a while
loop. I do not want to exit the while
loop though. I tried using exit
and break
but both exit the while loop.
The problem is that I don't know which folder the file I'm looking for is in, which is why I want to exit the current if
statement when I match the searched file so that I can move on to the next serial number.
I have a text file called drives-fw-sn.txt
that contains a list of serial numbers. Breakdown of code:
drives-fw-sn.txt
using a while
loopoutput_log
using find
Here's a snippet of my code (there are more than three test folders). Note that it still contains the exit
commands which exit the while
loop.
while read node; do
if find ./test1/*log* -maxdepth 2 -type f -name output_log -exec egrep -m 1 $node {} \; ; then
echo "Log SN $node available"
exit 1
fi
if find ./test2/*log* -maxdepth 2 -type f -name output_log -exec egrep -m 1 $node {} \; ; then
echo "Log SN $node available"
exit 1
fi
if find ./test3/*log* -maxdepth 2 -type f -name output_log -exec egrep -m 1 $node {} \; ; then
echo "Log SN $node available"
exit 1
fi
done < drives-fw-sn.txt
Upvotes: 0
Views: 8953
Reputation: 1220
This is actually pretty simple using the return
built-in. Inside the while
loop, set the if
statement inside a small function block. When the if
condition is met during the iterations, you can have it call the return
where the script will return to the place where the function was called and continue from that point. I will show you with an example:
#!/bin/bash
read -p 'Input: ' HEY
func() { if true; then return; fi; }
while true; do
echo "Input received!"
func && break
done
In the func
function, you have a very basic if
statement that can hold any conditional value you want, such as your multiple conditions. When you include the return
keyword, the if
statement will then send the interpreter's "program counter", if you will, back to the point where the func
function was called. Which in this case is inside the while
loop. So it will be as if the function was not even called and as you can see, the next command in the while loop is a break
keyword which will end the while
loop. The function that contains the if-then-return
code can be inside OR outside of your while
loop as long as the conditions you place inside the if
statement have been loaded into the interpreter first (bash reads scripts from top to bottom, similar to how C code is loaded).
There is also a lazy method and that is to wrap the entire script code inside a main function so you can use return
at any point in your script, no matter if it is a loop or conditional statement. Here is an example of the above script modified in this manner:
#!/bin/bash
MAIN() {
read -p 'Input: ' HEY
while true; do
if [ "$HEY" == "hello" ]; then
return
else
echo "Incorrect input! Try again!"
MAIN
fi
done
}
MAIN
echo "Correct input received!"
Doing it in this manner as well will help keep variables local rather than creating global variables. To do this, at any point in the MAIN
function you can define a variable as local so it only holds the value given to it while the MAIN
function is running. Once the function is complete, the variables and their values are no more.
Hope this helps.
Upvotes: 2
Reputation: 52132
continue
is the correct answer to your specific question how to "break out" of an if
statement. Be aware that the if
check is not actually checking if grep was successful, see the comment by chepner.
I would do this in a way that circumvents the problem in the first place:
Since you don't know which directory the file containing the serial number is going to be in, it doesn't matter in which order you're looking at them. Instead of listing all the directories separately and run find -exec
on each of them, you can have grep just try all the log files directly:
while read -r node; do
cat **/output_log | grep -m 1 "$node" && echo "Log SN $node available"
done < drives-fw-sn.txt
This requires the globstar shell option, shopt -s globstar
, to enable the **/
construct. Depending on your directory structure, you might not even need it and could use something like test*/*log*/output_log
instead.
cat
is used to prevent grep from checking other files once it has found a match.
The output is a little different: the matches are prepended by the filename, but that can be adjusted with the corresponding grep options (-h
to suppress filenames).
It also looks like you don't need regular expression matching; if so, you can use grep -F
for fixed strings, which should be faster.
Lastly, depending on what the serial numbers look like, you might want to use the -w
option (match only complete words) to avoid false positives due to substring matches.
Upvotes: 0
Reputation: 1642
There is no way to break out of the if
, per se. But from the looks of your example, you could the continue
command instead of exit
to iterate the loop immediately.
Upvotes: 1