So you can get explicit about the way the shell goes about locating commands in a few different ways. You can use...
command command_name
...to instruct the shell only to invoke the command_name if it is a $PATH
d executable. This is important in cases like yours because, when you've finished alias A
refers to alias B
which refers to alias A
usually something like 20 times before the alias
expansion quits recursing - and which lands you right back where you started. If you wanted to definitely only invoke a $PATH
d executable B
when calling A
and vice versa you can do...
alias A='command B' B='command A'
...which should avoid even calling functions named A
or B
. Otherwise - because the shell will not expand a quoted alias
as an alias
but will still call a function even if its command_name is quoted you can quote A
and B
in the definitions like...
alias A=\\B B=\\A
Ok, so it doesn't recurse twenty times. I could swear I had read that in some man
page, but I guess it is at least not true of either bash
or ksh
(having tested only either of them so far). It, in fact, recurses only twice:
n=0
A(){ echo not B; n=0; }
B(){ echo not A; n=0; }
alias A='echo "$((n+=1))";B' B='echo "$((n+=1))";A'
If I do the above and do...
A
...in bash
it prints:
1
2
not B
I guess this is relevant to this from the bash
manual:
- The first word of the replacement text is tested for aliases, but a word that is identical to an alias being expanded is not expanded a second time. This means that one may alias
ls
to ls -F
, for instance, and bash
does not try to recursively expand the replacement text.
I had read that before, but I didn't think it would test all expansions leading up to the current expansion when doing so - I figured it would only apply to the latest expansion in the chain. Anyway, that appears to be why.
I did note some interesting behavior otherwise though. After I had already declared both the aliases and the functions I went to rerun the commands, but with a little less intervening white space - like this:
A(){ echo not B; }; B(){ echo not A; }; A; B
...and that did...
1
2
3
4
5
6
not B
7
8
not A
Which means that the shell substituted the alias contents in for the function name - which is not a position one might normally expect an expansion to occur - did the echo
s and still redefined then executed the functions.
alias A='command B' B='command A'
. Or, if you're certain that the only reference you want to avoid is the alias you've just defined, thenalias A=\\B B=\\A
. – mikeserv Mar 01 '15 at 12:05B
is actually a function defined in my.bashrc
. I don't understand what you mean by "the only reference you want to avoid is the alias" - could you explain that further please? – texasflood Mar 01 '15 at 12:18