user2824889
user2824889

Reputation: 1185

Exiting a shell script from inside a while loop

I'm writing a simple shell script that should exit with 0 if an input string is found in a file, and exit with 1 if it isn't

INPSTR=$1

cat ~/file.txt | while read line
do
    if [[ $line == *$INPSTR* ]]; then
        exit 0
    fi
done

#string not found
exit 1

What's actually happening is that when the string is found, the loop exits, and the shell then goes to "exit 1". What's the correct way to exit from the shell script entirely while in a loop?

Upvotes: 20

Views: 12523

Answers (4)

Dawid Krysiak
Dawid Krysiak

Reputation: 51

One of the other ways would be to put most of your code in function and use return. This would probably look somehow like this:

#!/bin/bash

isTextInFile() {
    local needle="$1"

    cat ~/file.txt | while read line
    do
        if [[ $line == *$needle* ]]; then
            return 0
        fi
    done

    #string not found
    return 1
}

isTextInFile "$1"
exit

return will break both the loop, the subshell (introduced by using the pipe | usage, as other comments and answers mention) and the whole function.

Last exit without parameters will use code returned from the function.

Added bonus, your code could be made reusable with some more extra effort.

Upvotes: 0

Ivan
Ivan

Reputation: 41

For those who are looking for real variant for exit without double check in and after loop. I came up for simular task. To exit from whole script we can kill its task by pid. But need to get pid very carefully so not killing some important parent-parent id. The pid of loop must be $BASHPID, and the ppid (pid of script) will be $$ (if no more subshells used) So in this case command is

kill -9 $$

or if your shell child survives after killing parent it can be

kill -9 $$ $BASHPID

Upvotes: 0

Allien
Allien

Reputation: 101

you can catch return code of subshell using $? like this

INPSTR=$1
cat ~/file.txt | while read line
do
if [[ $line == *$INPSTR* ]]; then
    exit 0
fi
done
if [[ $? -eq 0 ]]; then
    exit 0
else
#string not found
    exit 1
fi

Upvotes: 10

anubhava
anubhava

Reputation: 785146

You need to avoid creating sub-shell in your script by avoiding the pipe and un-necessary cat:

INPSTR="$1"

while read -r line
do
    if [[ $line == *"$INPSTR"* ]]; then
        exit 0
    fi
done < ~/file.txt

#string not found
exit 1

Otherwise exit 0 is only exiting from the sub-shell created by pipe and later when loop ends then exit 1 is used from parent shell.

Upvotes: 14

Related Questions