Why is there an Alias loop error created here:

alias df 'printf "\n"; df -hP | column -t'

But not here:

alias df 'df -hP | column -t'

I realize I could call the alias something else and still have it work, however, I'm trying to understand the underlying operation.

  • I don't use csh, but it's possible that it assumes if the first command in the alias is the same as the name of the alias, it should use the non-alias, but otherwise it calls the alias. – Kevin Jan 9 '12 at 21:49
  • 2
    You can work around that by using the full path, /bin/df – Kevin Jan 9 '12 at 22:01
  • 1
    @Kevin I find that the only thing csh seems to be better than bash in is the alias syntax, mainly for formatting because it allows whitespace; that, and the fact that I don't have to create a function to open a program in the background (eg e () { emacs $1 & }) – vol7ron Jan 9 '12 at 23:38
  • You know you don't have to have the & in a function, right? You can just run command & straight from the command line. – Kevin Jan 9 '12 at 23:43
  • 2
    Another workaround: alias df 'printf "\n"; \df -hP | column -t' – Keith Thompson Jan 10 '12 at 1:04

It appears that when the alias name is also the first command, it's not interpreted as an alias, but beyond that it is. This can be worked around with the absolute path:

alias df 'printf "\n"; /bin/df -hP | column -t'

Or, as a Keith pointed out in a comment and answer, \ prevents alias expansion:

alias df 'printf "\n"; \df -hP | column -t'

This is explained in the tcsh man page (I suspect you're using tcsh, not csh); see the third quoted paragraph.

The shell maintains a list of aliases which can be set, unset and printed by the alias and unalias commands. After a command line is parsed into simple commands (see Commands) the first word of each command, left-to-right, is checked to see if it has an alias. If so, the first word is replaced by the alias. If the alias contains a history reference, it undergoes History substitution (q.v.) as though the original command were the previous input line. If the alias does not contain a history reference, the argument list is left untouched.

Thus if the alias for `ls' were `ls -l' the command `ls /usr' would become `ls -l /usr', the argument list here being undisturbed. If the alias for `lookup' were `grep !^ /etc/passwd' then `lookup bill' would become `grep bill /etc/passwd'. Aliases can be used to introduce parser metasyntax. For example, `alias print 'pr !* | lpr'' defines a ``command'' (`print') which pr(1)s its arguments to the line printer.

Alias substitution is repeated until the first word of the command has no alias. If an alias substitution does not change the first word (as in the previous example) it is flagged to prevent a loop. Other loops are detected and cause an error.

A good workaround is to precede a command with a \ character to inhibit alias expansion:

alias df 'printf "\n"; \df -hP | column -t'
  • The rule is the same in plain csh, and the same workaround works. – Gilles Jan 10 '12 at 1:15
  • I have to check, but I'm pretty sure it's csh (old setup) – vol7ron Jan 10 '12 at 5:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.