Shellcheck: defining an alias and using it inside the same(or sub) compound command (eg. `if` block) won't work

Created on 27 Jan 2020  路  2Comments  路  Source: koalaman/shellcheck

For new checks and feature suggestions

Here's a snippet or screenshot that shows the problem:

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

Here's what shellcheck currently says:

nothing

Here's what I wanted or expected to see:

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

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!

All 2 comments

+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!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

phagara picture phagara  路  4Comments

bbarker picture bbarker  路  3Comments

bje- picture bje-  路  3Comments

koalaman picture koalaman  路  4Comments

ghost picture ghost  路  4Comments