Can a bash script distinguish between being called as a script and being run as a "source"? [duplicate] - bash

This question already has answers here:
How to detect if a script is being sourced
(22 answers)
Closed 3 years ago.
I have a bash script that has inside it:
exit 1
When I "source" this script instead of running it, it causes the caller to exit.
Is there a way that the script can determine that it's being run with "source" and not as its script?

You can use this check inside your script:
[[ $0 = $BASH_SOURCE ]] && echo "normal run" || echo "sourced run"
Or using if/else/fi wherever you're calling exit:
if [[ $0 = $BASH_SOURCE ]]; then
exit 1
else
# don't call exit
echo "some error..."
fi

Related

Automatically exit when bash command produce return code non zero [duplicate]

This question already has answers here:
Automatic exit from Bash shell script on error [duplicate]
(8 answers)
Error handling in Bash [closed]
(15 answers)
Closed 4 years ago.
In bash how do we make the script to automatically exit if a command line return code is not zero. For example:
#!/bin/bash
cd /something_something
mv file_a /somedir/file_a # this produce an error
echo $? # This produce a non-zero output
echo "We should not continue to this line"
I know we can debug bash script with #!/bin/bash -x but sometime the script is too long, it run so fast, and we missed important error.
And I don't want to keep writing
[[ $? -ne 0 ]] && run next_command
There are lots of problems with using set -e. Just join the commands with &&, and test the result with an if statement.
if cd /something_something && mv file_a /somedir/file_a; then
echo $?
exit
fi
echo "Both cd and mv worked"

What is && and || in bash? [duplicate]

This question already has answers here:
What is the purpose of "&&" in a shell command?
(9 answers)
Closed 4 years ago.
I am trying to understand following pice of code:
for f in *.out; do sort -cg <$f &>/dev/null && res="sorted" || res="unsorted"; echo "File $f is $res."; done
For loop iterates through all .out files and gives each one as a parameter to sort, and the output of the sort is redirected into "nothing". But can someone explain what: && res="sorted" || res="unsorted" does?
A command after the && will only be executed if the previous command exited with a 0 (zero) status code. The other || works in the opposite way - a command after a || will only execute if the previous command exited with a non-zero exit code.
Here is a small example:
cat /some/file/that/is/missing && echo 'Found the file!' # doesn't print
cat /some/file/that/is/missing || echo 'Unable to find the file!' # will print
With the first line, the echo command will not execute since the cat command failed (because the file doesn't exist)
With the second line, we WILL see the echo command because the cat command failed.

Bash judgement gets the unexpected result [duplicate]

This question already has answers here:
Why should there be spaces around '[' and ']' in Bash?
(5 answers)
Closed 5 years ago.
This is the code of the my shell script:
#! /bin/bash
if ["$SHELL" = "/bin/bash"];then
echo "this is bash"
elif ["$SHELL" = "aa"];then
echo "this is aa"
else
echo "this is not /bin/bash, but $SHELL"
fi
why I execute the test_bash_03 script file gets the else result? shouldn't it be:this is bash ?
aircraftdeMacBook-Pro:bash_demo ldl$ ./test_bash_03
./test_bash_03: line 3: [/bin/bash: No such file or directory
./test_bash_03: line 5: [/bin/bash: No such file or directory
this is not /bin/bash, but /bin/bash
And I echo the $SHELL I also get the /bin/bash
aircraftdeMacBook-Pro:bash_demo ldl$ echo $SHELL
/bin/bash
You are missing a space after [ and before ].
The bash tries to execute a command named [/bin/bash instead of [ (which is test), then doesn't find that and has an exit code of 1 (false). So you end up in the else case.

Shell. How to exit the current script and go back to parent script that calls it? [duplicate]

This question already has answers here:
How do you return to a sourced bash script?
(3 answers)
Closed 9 years ago.
For example, A.sh calls B.sh inside the source code. The call is as the following in A.sh
#Inside A.sh
. ./B.sh
Now, some if..else statement happened in B.sh and decided to stop executing B.sh. How to make it go back to A.sh and keep executing the rest of the codes?
Thanks.
You've probably noticed that if you call exit from a file that's being sourced, you exit the entire shell, not just that file.
Instead, you can use return, which (in addition to returning from a function) will return control to the command following the . command.
Note that it is an error to return from a script that is being executed, rather than sourced, so make sure that you only use return outside of a function in a file that will be sourced.
The . basically means run this file in the current shell. That means that any exit or similar will exit the current (A) shell.
You need to make sure B is done in a different shell.
I haven't tested it, but ( . ./B.sh ) might work...
As others have stated, you can simplify event more: ./B.sh is also likely to work.
foo.sh:
#!/bin/bash
echo "hi"
./bar.sh
echo "done"
bar.sh:
#!/bin/bash
echo "bar here!"
[[ "1" == "1" ]] && exit 0
echo "oh no!"
Run foo.sh:
$ ./foo.sh
hi
bar here!
done

A simple if/else bash script which reacts to user's yes/no input? [duplicate]

This question already has answers here:
How do I prompt for Yes/No/Cancel input in a Linux shell script?
(37 answers)
Closed 7 years ago.
I basically have a bash script which executes 5 commands in a row. I want to add a logic which asks me "Do you want to execute command A" and if I say YES, the command is executed, else the script jumps to another line and I see the prompt "Do you want to execute command B".
The script is very simple and looks like this
echo "Running A"
commandA &
sleep 2s;
echo "done!"
echo "Running B"
commandB &
sleep 2s;
echo "done!"
...
Use the read builtin to get input from the user.
read -p "Run command $foo? [yn]" answer
if [[ $answer = y ]] ; then
# run the command
fi
Put the above into a function that takes the command (and possibly the prompt) as an argument if you're going to do that multiple times.
You want the Bash read builtin. You can perform this in a loop using the implicit REPLY variable like so:
for cmd in "echo A" "echo B"; do
read -p "Run command $cmd? "
if [[ ${REPLY,,} =~ ^y ]]; then
eval "$cmd"
echo "Done!"
fi
done
This will loop through all your commands, prompt the user for each one, and then execute the command only if the first letter of the user's response is a Y or y character. Hope that helps!

Resources