September 25, 2013

A bashism a week: aliases

In a response to my blogpost about bashisms in function names, reader Detlef L pointed out in a comment that aliases allow non-standard characters in their names, contrary to functions. They could then be used to, for example, set an alias of the run-parts(1) command (cf. the blog post).

Aliases indeed allow characters such as commas ( , ) to be used in the alias name. However, aliases are an extension to the POSIX:2001 specification and are therefore bashisms. Moreover, the characters set defined by POSIX does not include dashes.

Last but not least, aliases belong to the list of shell features that are usually "disabled" when the shell is run in non-interactive mode. I.e.


$ bash <<EOF
alias true=false;
if true; then echo alias disabled; else echo alias enabled; fi
EOF

alias disabled
$ bash -i <<EOF # force interactive mode
alias true=false;
if true; then echo alias disabled; else echo alias enabled; fi
EOF

$ alias true=false;
$ if true; then echo alias disabled; else echo alias enabled; fi
alias enabled
$ exit


To add to the fun of different behaviours, other shells always expand aliases.

If you decide to play with aliases you should note one thing: they are only enabled from the line after the definition. E.g. note the difference below

$ dash -c 'alias foo="echo foo"; foo'
dash: foo: not found
$ dash -c 'alias foo="echo foo";
foo'
foo

1 comment:

  1. In scripts, sometimes they are enabled even more later:

    $ mksh -c 'while true; do
    > alias foo="echo foo"
    > foo
    > break
    > done
    > echo bar
    > foo
    > '
    mksh: foo: not found
    bar
    foo

    Basically: “in the input translation unit after the one it defines has been run”. Aliases are expanded in the lexer, which can be seen easily here:

    $ alias foo=bar
    $ baz() {
    > foo
    > }
    $ typeset -f baz
    baz() {
    bar
    }

    So the order is: first, the alias command itself must have been run (executed), to make the alias definition known. Then, a new lexer invocation must be started (while…done is parsed as one, then run). Only then, the alias is available.

    ReplyDelete