问题
Background:
I'm trying make a function that runs commands on a set interval because I don't have access to a "watch" program. Simplified to it's most basic from, the function I'm trying to write is runit() { $1; }
.
What works:
This works fine and dandy when I pass it things that aren't aliases. For example, runit "ls -l"
works fine. I get the full output from the ls -l
command.
What doesn't work:
The problem starts when I pass it an alias. For example, setting alias ll="ls -l"
then calling runit "ll"
will result in -bash: ll: command not found
.
Things I have tried:
When I hard-code the alias runit() { ll; }
, it works fine and gives me what I expect.
I feel like I might be overlooking something, but I can't quite place my finger on it.
Why would hard-coding the alias work fine, but passing it into the function fail?
Is there a way to accomplish what I'm attempting to do?
回答1:
From the bash
man page discussion of aliases (emphases mine):
Aliases are expanded when a command is read, not when it is executed. Therefore, an alias definition appearing on the same line as another command does not take effect until the next line of input is read. The commands following the alias definition on that line are not affected by the new alias. This behavior is also an issue when functions are executed. Aliases are expanded when a function definition is read, not when the function is executed, because a function definition is itself a compound command. As a consequence, aliases defined in a function are not available until after that function is executed. To be safe, always put alias definitions on a separate line, and do not use alias in compound commands.
You can observe this effect in functions by using the type command:
$ run_it () { ll; }
$ type run_it
You should see that the body of the function contains a call to ls -l
, not ll
.
The last sentence of the section on aliases:
For almost every purpose, aliases are superseded by shell functions.
My interpretation of that line is: if you think you want to use an alias, try writing a function first. Don't use an alias unless the function demonstrably fails to do what you need.
回答2:
You can use eval
like this:
$ runit() { eval $1; }
$ alias ll="ls -l"
$ runit "ll"
eval
will expand any alias in $1
before the execution.
回答3:
One way to solve this problem is to define a shell function rather than an alias.
ll () {
ls -l "$@"
}
The alias is expanded as a macro on command input, whereas the shell function is matched when the command is executed. This is a perfect example of how the shell's macro processor language is good for interactive grace but rather complicates actual programming.
来源:https://stackoverflow.com/questions/14527581/execute-a-passed-alias-inside-a-function