This question was inspired in part by this one.
alias foo='ls -1 $1'
foo /etc
displays the contents of /etc, one item per line.
ls -1 /etc | tail
displays the last ten items in /etc.
But
alias foo='ls -1 $1 | tail'
foo /etc
displays: tail: error reading `/etc': Is a directory
I have found variable expansion in aliases to be flaky, and not recommended:
http://www.gnu.org/software/bash/manual/bashref.html#Aliases
Use a function instead: function foo() { ls -1 $1; }
Aliases done this way will only expand from the set of parameters:
$ alias foo='ls -1 $1 | tail'
$ foo .
# Type Esc-C-e: this expands aliases/globs/environment variables...
# ... And the result of the expansion is:
$ ls -1 | tail .
# $1 has disappeared
$ set bar # set $1...
$ foo . # again, Esc-C-e
$ ls -1 bar | tail .
The direct answer to your question: it is luck that the first case matches what you expect.
You have written your aliases assuming that $1 will represent the first "argument" to your alias. In fact, aliases in bash do not accept arguments, they merely replace the alias text with the stuff in quotes that you assigned it. So what does your $1 actually do?
Separate from aliases, in bash, $0
expands to the first thing typed to being the script or shell you are in (the command). $1
is the first argument (or second thing typed). Since you are typing in a shell at the command line, your shell was likely started by a terminal or window manager running the command bash
with no arguments.
Try this from the command line:
$ echo $0
bash
$ echo $1
# prints nothing
So in your first case,
foo /etc
expands foo to get
ls -1 $1 /etc
and since $1 is null,
ls -1 /etc
also, if you pipe that to tail by adding | tail
it works fine.
In your 2nd case
foo /etc
expands foo to get
ls -1 $1 | tail /etc
and since $1 is null,
ls -1 | tail /etc
which gives that error you got, because the command after the pipe is in error: tail
cannot operate on the directory /etc