我需要一个 bash 函数来接受可变数量的参数。这些参数是其他命令,如ls /root
、echo HI
、git clone http:// ....
等rm
。该函数按顺序执行命令
该函数必须接受以下参数:
myfun <arbitrary set of commands>
请注意,每个命令本身可能有一组任意的参数。
myfun echo H ls /root git clone http://.... /home/myh/git/x1
myfun 应该按如下方式执行
echo H
ls /root
git clone http://.... /home/myh/git/x1
传递参数的方式myfun
可以改变。有没有办法实现所需的行为?
答案1
你可以有点这样做,但是,Michal Przybylowicz 建议,你不应该。如果你知道如果你想这样做,你可以跳过;否则,请考虑这些替代方案。
- 如果您的目标是在一行中发出多个相继运行的命令,请用 将它们分隔开
;
。 - 如果您希望它们同时运行,请用 . 将它们分开
&
。这样,除了最后一个之外,其他所有任务都会在后台运行。如果您希望最后一个任务在后台运行,请在&
其后面也加上 。 - 如果您希望它们一个接一个地运行,但当其中一个失败时停止,请用
&&
而不是将它们分开;
。 - 如果您希望能够将重定向应用于 while 命令块,请将它们括在 中
{
}
。开头的 后面需要一个空格{
。结尾的}
必须出现在新行上,或者在;
其前面有一个。在同一行的 结尾后应用重定向}
。例如,{ echo H; ls /root; } >out.txt
。 - 如果你希望函数将其参数作为命令运行,原因是你想这样做其他有参数的东西,那么这个可能是合理的,但你应该考虑其他选择。如果你想跟踪它们,并且命令是交互输入的,那么你可能能够使用 shell 自己的历史记录功能;请参阅
help history
和help fc
。如果你想立即显示将要运行的命令以及运行它们,请使用set -x
;请参阅help set
了解详情。
您通常不应该编写一个将其每个参数作为完整命令运行的函数,原因是使用这样的函数会很麻烦且容易出错,因为您必须引用由多个单词组成的每个参数(即,将一个或多个参数传递给命令)。这似乎并不那么糟糕……直到您意识到您的某些参数本身可能需要引用,在这种情况下您也必须引用引号。这是可行的,但远非理想。
作为问题的具体示例,请考虑您建议运行的可以调用函数的命令:
myfun echo H ls /root git clone http://.... /home/myh/git/x1
这行不通。怎么myfun
知道一个命令在哪里结束,下一个命令在哪里开始?
如果你真的想要实现这一点,一个合理的方法是使用eval
内置函数(参见help eval
)。您可以随意命名该函数,不必将其命名为eval_all
:
eval_all() { for cmd; do eval "$cmd"; done; }
for cmd
效果与 相同for cmd in "$@"
。使用您喜欢的变量名称cmd
;只需记住进行相应更改即可$cmd
。如果您想避免写入cmd
函数外使用的变量:
eval_all() { local cmd; for cmd; do eval "$cmd"; done; }
无论您决定如何编写此函数,如果您想使用它来运行命令echo H
和ls
,您可以像这样调用它:
eval_all 'echo H' ls
但你已经可以这样做了,这样更好:
echo H; ls
如果您还希望它运行命令touch 'honest $$$$ ideas.txt'
,您可以这样调用它:
eval_all 'echo H' ls 'touch '\''honest $$$$ ideas.txt'\'
还有其他方法可以引用单引号。没有一种方式特别漂亮。没有一种方式比以下方式更好:
echo H; ls; touch 'honest $$$$ ideas.txt'