Summary: I define a new alias abc2 inside an if block and I call it inside the same if block. This won't work because if is compound command and although abc2 will get defined inside it(and seen as defined via alias -p, it won't get expanded (To be safe, always put alias definitions on a separate line, and do not use alias in compound commands. from man 1 bash).
#!/bin/bash --login
#originally this was inside ~/.bashrc
#to emulate that here:
shopt -s expand_aliases
#shopt -s login_shell #this won't work like that! it remains off, unless I use "--login" shebang arg!
unset abc1
unset abc2
echo 'alias list before the "if" is:'
alias -p |grep abc
#FIXME: the 'abc2' alias call inside the 'if' doesn't work in: GNU bash, version 5.0.11(2)-maint (x86_64-pc-linux-gnu) aka 5.0.r660.gaa99ef52-1 and in 5.0.r671.g9831556e-1 because "do not use alias in compound commands." from `man 1 bash`
alias abc1="echo 'abc1 executed'"
abc1
if true; then
alias abc2="echo 'abc2 executed'"
echo 'alias list inside "if" is:'
alias -p |grep abc #both abc1 and abc2 are present
shopt expand_aliases #it's "on"
shopt login_shell #is 'on' only if this is inside ~/.bashrc or when using sheband arg "--login" to 'bash'
[[ $- != *i* ]] || echo "shell is interactive" #this will show!
abc1 #works
abc2 #XXX doesn't work: "-bash: abc2: command not found", because I'm defining and using the alias inside the same compound command (which 'if ;then...fi' is).
if true; then
abc2 #still won't work
fi
fi
abc2 #works
echo 'alias list outside of "if" is:'
alias -p |grep abc #both abc1 and abc2 are present
nothing
Some warning about defining and using the new alias within the same compound command (eg. within the same if ...;then ... fi) or a within a subblock of it.
As a workaround, in my real life sample I got to use two if blocks, one after the other, one for defining the aliases and the other for calling one of them.
Maybe shellcheck could recommend using functions instead?
For almost every purpose, aliases are superseded by shell functions. (from man 1 bash)
They seem to work, here's the same example with an added abc3 as function(instead of alias) which does seem to work:
#!/bin/bash --login
#originally this was inside ~/.bashrc
#to emulate that here:
shopt -s expand_aliases
#shopt -s login_shell #this won't work like that! it remains off, unless I use "--login" shebang arg!
unset abc1
unset abc2
unset abc3
echo 'alias list before the "if" is:'
alias -p |grep abc
#FIXME: the 'abc2' alias call inside the 'if' doesn't work in: GNU bash, version 5.0.11(2)-maint (x86_64-pc-linux-gnu) aka 5.0.r660.gaa99ef52-1 and in 5.0.r671.g9831556e-1 because "do not use alias in compound commands." from `man 1 bash`
alias abc1="echo 'abc1 executed'"
abc1
if true; then
alias abc2="echo 'abc2 executed'"
abc3() {
echo "abc3 executed"
}
echo 'alias list inside "if" is:'
alias -p |grep abc #both abc1 and abc2 are present
shopt expand_aliases #it's "on"
shopt login_shell #is 'on' only if this is inside ~/.bashrc or when using sheband arg "--login" to 'bash'
[[ $- != *i* ]] || echo "shell is interactive" #this will show!
abc1 #works
abc2 #XXX doesn't work: "-bash: abc2: command not found", because I'm defining and using the alias inside the same compound command (which 'if ;then...fi' is).
abc3 #works
if true; then
abc2 #still won't work
abc3 #works
fi
fi
abc2 #works
echo 'alias list outside of "if" is:'
alias -p |grep abc #both abc1 and abc2 are present
+1. It's very easy to forget that aliases are looked up and expanded at _parse_ time, but commands (including alias) and functions are looked up and run at _execution_ time, hence the discrepancy that @temporaryrespite noticed.
While exceedingly rare in practice, this is a great example of the kind of arcane, surprising, ungoogleable shell knowledge that ShellCheck can offer. A warning has been added. Thanks!
Most helpful comment
While exceedingly rare in practice, this is a great example of the kind of arcane, surprising, ungoogleable shell knowledge that ShellCheck can offer. A warning has been added. Thanks!