Env: Ubuntu 14.04
I have a file called bc
on my home folder. The whole content of the file is
func() {
local a b=()
echo $0
}
func
Note there's no #!/bin/bash
at the beginning.
Then, if I do /bin/bash ~/bc
I get
/home/dev/bc
as expected.
However, if I source it instead . ~/bc
I get the following error:
bash: /home/dev/bc: line 2: syntax error near unexpected token `('
bash: /home/dev/bc: line 2: ` local a b=()'
I am assuming a different shell is executed for sourcing. If that is the case, then how can I change it?
If I do a chsh
I get
dev@c1:~$ sudo chsh
[sudo] password for dev:
Changing the login shell for root
Enter the new value, or press ENTER for the default
Login Shell [/bin/bash]:
—— from comments ——–
echo $SHELL
returns /bin/bash
Best Answer
The problem is almost definitely an alias. When you do:
You load a new shell. You get a fresh start. That executable isn't saddled with all of the stuff you put in your initialization files - rcs - because those are only sourced by default for interactive shells, which is not to mention any additional logic accrued since.
Aliases are weird. Aliases are parser expansions - they're the very first kind of expandable object most shells support, and they are expanded in ways many don't expect.
bash
, in fact, discourages their use - for whatever reason - by disablingalias
expansions by default in any non-interactive shell. And so if an alias causes that error - and I'm pretty sure that's the problem - then even sourcing your environment files would likely still not elicit the same error output when you/bin/bash
, anyway.When I say aliases are weird it is because they are expanded on a different level than other types of shell expansions. Probably this is most keenly obvious in a function definition context; wherein no shell expansions occur - as those are reserved for the function's later execution - except aliases without twice-evaluating the expression. And aliases are never expanded during function execution (again, short of
eval
), because they were already expanded during its definition.Here's an example:
...prints...
The first time the
alias
nameda
is expanded is when I do:This is possible because the
()
parens are shell tokens - not reserved words like{}
- and so they can delimit a word without whitespace - which makes them particularly useful for things like function and array declarations as the parser performs macro expansion to arrive at an executable statement. The result of the above expansion is...The last time it is expanded transforms:
...into...
You see, typical shell expansions occur in a pre-delimited context - they are bounded on all sides by control operators like:
In this way most shell expansions serve as a quoting mechanism in and of themselves - quotes expanded out of a variable do not recursively delimit further quoted contexts because the expansion quoted them. Alias expansion occurs before this, though - aliases are expanded if recognized by the parser as it scans the first shell word in a simple command - before it scans in the rest of it. So if the expansion results in more than a single simple command, well... then so be it.
My assumption is you have an
alias
declared forfunc
- that would be the most simple explanation - but because aliases can chain if they're defined with a trailing space - and will also be expanded within a function definition - there's no way of knowing for certain given only the information you provide. I think I can reproduce your error, though. This is close:...which prints...
So just do:
And let us know.