Reputation: 11002
My understanding is that when I execute a script inside a BASH shell using syntax like $ ./myscript.sh
a sub-shell is started and the code runs in that shell, with STDOUT and STDERR output being printed on my shell, STDIN is taken from my shell. This is how script are interactive.
The top line of the file "myscript" is #!/bin/bash
, this states the interpreter to be used to execute the syntax within the script file.
If I use the syntax source myscript.sh
the code in my script is "pulled" in to my current environment and executed there, rather than in a sub-shell. I can't make the following code run in a script that I call with $ ./myscript.sh
and effect my current shell:
#!/bin/bash
PS1='`
if [ $? -eq 0 ];
then echo -n "\[\033[00;35m\]\u\[\033[01;32m\]@\[\033[00;35m\]\h\[\033[00;32m\](\[\033[01;35m\]\W\[\033[01;32m\])\[\033[00;32m\]\$";
else echo -n "\[\033[00;35m\]\u\[\033[01;31m\]@\[\033[00;35m\]\h\[\033[01;31m\](\[\033[35m\]\W\[\033[31m\])\[\033[00;31m\]\$";
fi`\[\033[0m\]'
If I drop the #!/bin/bash
and use source
this script changes my command prompt. Can it be arranged in a script in such a fashion that I can call it with $ ./myscript.sh
and it will make the change to my current shell, not the sub shell?
Upvotes: 3
Views: 6315
Reputation: 155
I'm not quite sure what you're trying to do, so I don't think I can solve your problem (I don't know how $?
is being set). That said, what I just discovered today may help people with similar issues.
The OP's script fails its purpose because the changes it attempts to apply are lost when the subshell exits. I've struggled with this several times before, and was again wrestling with it today. I came up with a different approach, rewriting the script to generate but not apply the arguments.
To address the OP's difficulty, create the following script which follows the spirit of the OP's script (I took liberties with the prompt strings and with the conditional statement):
#!/usr/bin/env bash
# file: setps1
if [ "$1" -eq 0 ]; then
echo -n $'\e[35;1m\\u\e[m@\e[32;1m\\h\e[m(\e[32;1m\\W\e[m)\$ '
else
echo -n $'\e[35;1m\\u\e[m@\e[31;1m\\h\e[m(\e[31;1m\\W\e[m)\$ '
fi
Then call it with:
PS1=$( ./setps1 1 )
Note that this also works for commands requiring multiple arguments. In my case, the script originally called enable
with three computed arguments and it failed in the familiar way. I rewrote the script to only output the three computed arguments and installed the script in /usr/local/bin
for easy access. Using the script to supply the arguments to enable
without having to supply complicated paths makes using my builtin more user-friendly.
Upvotes: 0
Reputation: 241848
Once you have called a script without source
, it is running in a subshell and there is no way to change the environment of the parent shell.
You can source a script with a shebang line. It is simply ignored when sourced.
Upvotes: 7