Reputation: 56948
Is there any way to mark a script to be "run as source" so you don't have to add the source
or "." command to it every time? i.e., if I write a script called "sup", I'd like to call it as
sup Argument
rather than
source sup Argument
or
. sup Argument
Basically, I'm trying to use cd
within a script.
Upvotes: 25
Views: 33864
Reputation: 125396
Bash forks and starts a subshell way before it or your kernel even considers what it's supposed to do in there. It's not something you can "undo". So no, it's impossible.
Thankfully.
Look into bash
functions instead:
sup() {
...
}
Put that in your ~/.bashrc
.
Upvotes: 36
Reputation: 2231
It is not possible to source a script in your current environment if you sub-shell the script at invoke.
However, you can check that script is sourced and force the script to terminate if not:
if [ -z "$PS1" ] ; then
echo "This script must be sourced. Use \"source <script>\" instead."
exit
fi
The same way, you can force a script not to be sourced but to be sub-shelled instead (preserve current shell environment):
if [ "$PS1" ] ; then
echo "This script cannot be sourced. Use \"./<script>\" instead."
return
fi
Both versions are available as gists: see please source and don't source.
Upvotes: 8
Reputation: 753725
Create an alias for it:
alias sup=". ~/bin/sup"
Or along those lines.
See also: Why doesn't cd work in a bash shell script?
Answering comment by counter-example: experimentation with Korn Shell on Solaris 10 shows that I can do:
$ pwd
/work1/jleffler
$ echo "cd /work5/atria" > $HOME/bin/yyy
$ alias yyy=". ~/bin/yyy"
$ yyy
$ pwd
/work5/atria
$
Experimentation with Bash (3.00.16) on Solaris 10 also shows the same behaviour.
Upvotes: 10
Reputation: 16761
When you are running a shell, there are two ways to invoke a shell script:
Executing a script spawns a new process inside which the script is running. This is done by typing the script name, if it is made executable and starts with a
#!/bin/bash
line, or directly invoking
/bin/bash mycmd.sh
Sourcing a script runs it inside its parent shell (i.e. the one you are typing commands into). This is done by typing
source mycmd.sh
or . mycmd.sh
So the cd inside a shell script that isn't sourced is never going to propagate to its parent shell, as this would violate process isolation.
If the cd is all you are interested about, you can get rid of the script by using cd "shortcuts"... Take a look into the bash doc, at the CDPATH env var.
Otherwise, you can use an alias to be able to type a single command, instead of source or .:
alias mycmd="source mycmd.sh"
Upvotes: 25