Up to now I thought that a semicolon in the shell has (somehow) the same meaning as a line break. So I was surprised that for

alias <name>=<replacement text>; <name>

<name> is unknown while it is known in the next line. csh, tcsh, sh, ksh and bash behave the same. At least for csh it does not matter if alias is used directly or if a script is sourced before the semccolon--the aliases are not known after ; but the are known in the next command line. Is this a bug or is this behavior intended?

  • 1
    "I thought that a semicolon in the shell has (somehow) the same meaning as a line break" Nearly. Not quite! Commented Nov 2, 2015 at 20:10
  • 2
    The interpretation of semicolon and newline depends on how the parser is called. For the "dot" command, the Bourne Shell calls the parser with the "NLFLG" that tells it to treat newline and semicolon equal in some situations, but this is not the case elsewhere. In general, semicolon and linebreak are not equivalent as you can have a linebreak, where a semicolon would cause a syntax error.
    – schily
    Commented Nov 3, 2015 at 9:08

3 Answers 3


The alias syntax you are using is inappropriate for a POSIX shell, for a POSIX shell, you need to use:

alias name='replacement'

But for all shells, this cannot work as the alias replacement is done early in the parser.

Before your alias setup is executed, the whole line was read by the parser and for this reason, your command line wil not work.

If the alias appears on the next command line, it will work.

  • In addition, some shells like yash or zsh would not expand the alias in shell -c 'alias name=replacement<newline>replacement'. For AT&T ksh, you'd have the problem with sourced scripts. Commented Nov 2, 2015 at 13:46
  • I need to use the csh in this case--there no = is used in the alias syntax. Commented Nov 2, 2015 at 13:52
  • @user3224237 - this has nothing to do with the =. it is because the alias expansion happens when the shell first sees the line, which is before you define the alias.
    – cas
    Commented Nov 2, 2015 at 23:24
  • @Stéphane Chazelas The behavior with "sourced" scripts is caused by the fact that the Bourne shell completely parses such files before they are execured. Ksh is based on the Bourne Shell source and everything that was not changed behaves the same.
    – schily
    Commented Nov 3, 2015 at 8:55
  • @schily, yes, it's the same reason for zsh/yash -c 'code' where code is parsed as a whole. It doesn't seem to be the case for the Bourne shell. So I suppose the Bourne shell parses that code there one line at a time. Commented Nov 3, 2015 at 9:04

This behavior is intended and specified by POSIX under Alias Substitution.

An alias was substituted right after the shell perform Token Recognition and before any Grammar Rules applied. At the time you called the alias <name>, the command alias wasn't executed.


If you really want one-liner, then you can use function instead of alias.

E.g. you make py3 alias, but it only works in second line:

$ alias py3=python3; py3 -c 'print("hello, world")'

Command 'py3' not found, did you mean:

  command 'py' from deb pythonpy
  command 'hy3' from deb python3-hy
  command 'pyp' from deb pyp

Try: sudo apt install <deb name>

$ py3 -c 'print("hello, world")'
hello, world

You can define py3 as function instead of alias:

$ function py3() { python3 "$@"; }; py3 -c 'print("hello, world")'
hello, world

Or export -f before used in child process later:

$ function py3() { python3 "$@"; }; export -f py3; bash -c "py3 -c 'print("'"hello, world"'")'"
hello, world

And if you be aware the difference of variable vs alias/function, then you can use variable too:

$ py3='python3'; $py3 -c 'print("hello, world")'
hello, world

and no need export -f:

$ py3='python3'; bash -c "$py3 -c 'print("'"hello, world"'")'"
hello, world

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .