Alias scoping in bash functions
An alternative solution is to paste those commands into a text file instead of a function block. Something like:
## This is needed to make the sourced aliases available
## within the script.
shopt -s expand_aliases
source /some/environment/setup/script.sh
aliasToSetupSomeSoftwareVersion
anotherAliasForOtherSoftware
source /maybe/theres/another/script.sh
runSomeOtherSetup
Save that as setup1.sh
wherever you like. The trick is to then source this file, not execute it:
$ source setup1.sh
That will run the aliases that are in the script and also make them available to your current shell.
You can further simplify the process by adding this to your .bashrc
:
alias setupLotsOfThings="source setup1.sh"
Now you can simply run setupLotsOfThings
and get the behavior you wanted from the function.
Explanation
There are two issues here. First, aliases are not available to the function they are declared in but only once that function has exited and second that aliases are not available within scripts. Both are explained in the same section of man bash
:
Aliases are not expanded when the shell is not interactive, unless the expand_aliases shell option is set using shopt (see the description of shopt under SHELL BUILTIN COMMANDS below).
The rules concerning the definition and use of aliases are somewhat confusing. Bash always reads at least one complete line of input before executing any of the commands on that line. Aliases are expanded when a command is read, not when it is executed. Therefore, an alias definition appearing on the same line as another command does not take effect until the next line of input is read. The commands following the alias definition on that line are not affected by the new alias. This behavior is also an issue when functions are executed. Aliases are expanded when a function definition is read, not when the function is executed, because a function definition is itself a compound command. As a consequence, aliases defined in a function are not
available until after that function is executed. To be safe, always put alias definitions on a separate line, and do not use alias in com‐ pound commands.
Then, there is the difference between executing and sourcing a file. Basically, running a script makes it run in a separate shell while sourcing it makes it run in the current shell. So, sourcing setup.sh
makes the aliases available to the parent shell while executing it as a script would not.
Actually, your aliases are available after the function is loaded! You can use them in your interactive shell, or in your .bashrc
after executing the function.
The restriction is that aliases in a function definition are expanded when the function definition is read, not when the function is evaluated. This is a limitation of bash. So this will work:
function setupLotsOfThings() {
source aliases.sh
}
setupLotsOfThings
fooAlias
But not this:
function setupLotsOfThings() {
source aliases.sh
}
function useTheAliases() {
fooAlias
}
setupLotsOfThings
useTheAliases
If you need aliases that are usable inside functions and can be defined after the function is parsed, make them functions instead. Remember that you can use the command
builtin to invoke an external command from a function of the same name.