The root of the problem is an anomaly in how the source command works. From the bash man page, in the "Shell Builtin Commands" section:
. filename [arguments]
source filename [arguments]
[...] If any arguments are supplied, they become the positional parameters when filename is executed. Otherwise the positional parameters are unchanged.
...which means you can override the main script's arguments by supplying different arguments to the sourced script, but you can't just not pass arguments to it.
Fortunately, there's a workaround; just source the script in a context where there are no arguments:
#!/bin/bash
wrapperfunction() {
source ./a.sh
}
wrapperfunction
Since no arguments are supplied to wrapperfunction, inside it the arg list is empty. Since a.sh's commands are run in that context, the arg list is empty there as well. And variables assigned inside a.sh are available outside the function (unless they're declared as local or something similar).
(Note: I tested this in bash, zsh, dash, and ksh93, and it works in all of them -- well, except that dash doesn't have the source command, so you have to use . instead.)
Update: I realized you can write a generic wrapper function that allows you to specify a filename as an argument:
sourceWithoutArgs() {
local fileToSource="$1"
shift
source "$fileToSource"
}
sourceWithoutArgs ./a.sh
The shift command removes the filename from the function's arg list, so it's empty when the file actually gets sourced. Well, unless you passed additional arguments to the function, in which case those will be in the arg list and will get passed on... so you can actually use this function to replace both the without-args and the with-args usage of source.
(This works in bash and zsh. If you want to use it in ksh, you have to remove local; and to use it in dash, replace source with .)
btoa. It's the code being sourced frombintoa. That's the reason of existence ofsource. Otherwise, a standard execution in a subshell would be enough.source.#!/bin/bash ./a.shfor arg in "$@"; do shift; donesourceis that I need variables exported ina.shto be available afterward inb.sh.