Bash:在脚本中执行多命令行字符串
Bash: execute a multi-command line string in a script
在一个文件中,有一些像这样的多命令行:
cd /home/user; ls
在 bash 脚本中,我想执行这些命令,并在最后一个命令中添加一些参数。例如:
cd /home/user; ls -l *.png
我认为做这样的事情就足够了:
#!/bin/bash
commandLine="$(cat theFileWithCommandInside) -l *.png"
$commandLine
exit 0
但是它说:
/home/user;: No such file or directory
换句话说,“;”字符不再意味着 "end of the command": shell 正在尝试在主文件夹中找到一个名为 "user;" 的目录...
我尝试替换“;”用"&&",结果是一样的
关键是:eval
这里固定脚本(看第三行):
#!/bin/bash
commandLine="$(cat theFileWithCommandInside) -l *.png"
eval $commandLine
exit 0
为什么不在脚本中执行命令本身,而是 "importing" 它们?
#!/bin/bash
cd /home/user; ls -l *.png
exit 0
将命令包装成一个函数:
function doLS() {
cd user; ls $@
}
$@
扩展为传递给函数的所有参数。如果您(或代码片段作者)添加需要预定义参数数量的函数,您可能会发现位置参数 </code>、<code>
、... 很有用。
作为主要脚本的维护者,您必须确保提供此类代码段的每个人都提供 "interface" 您的代码使用(即他们的代码定义了您的程序调用的函数,并且他们的函数处理您的程序传递的参数)。
使用 source
或 .
将函数导入您的 运行ning shell:
#!/bin/bash
source theFileWithCommandInside
doLS -l *.png
exit 0
我想补充一些关于 ;
主题的想法:
In other words, the ";" character doesn't mean anymore "end of the
command": The shell is trying to find a directory called "user;" in
the home folder...
;
不像在 C 风格语言中那样用于终止语句。相反,它用于分隔应在 list 中按顺序执行的命令。在 subshell:
中执行两个命令的示例
( command1 ; command2 )
如果列表是 组 的一部分,则必须在 ;
:
之后
{ command1 ; command2 ; }
在您的示例中,将不会执行标记化和通配符(替换 *
)(如您所料),因此您的代码不会 运行 成功。
你的问题的重点是执行存储在字符串中的命令。有数千种方法可以间接执行。但最终,bash 必须参与。
那么为什么不显式调用 bash 来完成这项工作呢?
bash -c "$commandLine"
来自文档:
-c string
If the -c option is present, then commands are read from string. If there are arguments after the string, they are assigned to the positional parameters, starting with [=11=].
使用 <(...) 形式
sh <(sed 's/$/ *.png/' theFileWithCommandInside)
在一个文件中,有一些像这样的多命令行:
cd /home/user; ls
在 bash 脚本中,我想执行这些命令,并在最后一个命令中添加一些参数。例如:
cd /home/user; ls -l *.png
我认为做这样的事情就足够了:
#!/bin/bash
commandLine="$(cat theFileWithCommandInside) -l *.png"
$commandLine
exit 0
但是它说:
/home/user;: No such file or directory
换句话说,“;”字符不再意味着 "end of the command": shell 正在尝试在主文件夹中找到一个名为 "user;" 的目录...
我尝试替换“;”用"&&",结果是一样的
关键是:eval
这里固定脚本(看第三行):
#!/bin/bash
commandLine="$(cat theFileWithCommandInside) -l *.png"
eval $commandLine
exit 0
为什么不在脚本中执行命令本身,而是 "importing" 它们?
#!/bin/bash
cd /home/user; ls -l *.png
exit 0
将命令包装成一个函数:
function doLS() {
cd user; ls $@
}
$@
扩展为传递给函数的所有参数。如果您(或代码片段作者)添加需要预定义参数数量的函数,您可能会发现位置参数 </code>、<code>
、... 很有用。
作为主要脚本的维护者,您必须确保提供此类代码段的每个人都提供 "interface" 您的代码使用(即他们的代码定义了您的程序调用的函数,并且他们的函数处理您的程序传递的参数)。
使用 source
或 .
将函数导入您的 运行ning shell:
#!/bin/bash
source theFileWithCommandInside
doLS -l *.png
exit 0
我想补充一些关于 ;
主题的想法:
In other words, the ";" character doesn't mean anymore "end of the command": The shell is trying to find a directory called "user;" in the home folder...
;
不像在 C 风格语言中那样用于终止语句。相反,它用于分隔应在 list 中按顺序执行的命令。在 subshell:
( command1 ; command2 )
如果列表是 组 的一部分,则必须在 ;
:
{ command1 ; command2 ; }
在您的示例中,将不会执行标记化和通配符(替换 *
)(如您所料),因此您的代码不会 运行 成功。
你的问题的重点是执行存储在字符串中的命令。有数千种方法可以间接执行。但最终,bash 必须参与。
那么为什么不显式调用 bash 来完成这项工作呢?
bash -c "$commandLine"
来自文档:
-c string
If the -c option is present, then commands are read from string. If there are arguments after the string, they are assigned to the positional parameters, starting with [=11=].
使用 <(...) 形式
sh <(sed 's/$/ *.png/' theFileWithCommandInside)