Why does variable expansion within an alias work “

2019-06-26 04:59发布

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

3条回答
干净又极端
2楼-- · 2019-06-26 05:15

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 .
查看更多
等我变得足够好
3楼-- · 2019-06-26 05:22

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; }

查看更多
兄弟一词,经得起流年.
4楼-- · 2019-06-26 05:25

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

查看更多
登录 后发表回答