我有多个要在bash中运行的命令。因为这些cmd本质上是交互式的,所以我不能将它们放在脚本中并作为脚本运行(./cmds
不适用)
但是我想逐行将它们放在文件(如文本文件)中,并作为命令行逐行运行(而不是脚本):
$ bash < my_cmds_as_text_line_by_line.txt
#my_cmds_as_text_line_by_line.txt
cmd1
cmd2
cmd3
问题 以上执行与:
bash -c cmd1
bash -c cmd2
bash -c cmd3
答案 0 :(得分:1)
您的问题的答案是“不,两者不相同”。
如果您运行:
bash < my_cmds_as_text_line_by_line.txt
其中提到的文件包含:
cmd1
cmd2
cmd3
与以下不同:
bash -c "cmd1"
bash -c "cmd2"
bash -c "cmd3"
因为每行现在都在自己的全新bash
shell中执行,而不是可能受先前命令影响的行,
想象cmd1
是cd /usr
,在第二种方案中,它将目录更改为/usr
,然后退出bash
shell,并开始一个新的shell-一起在其他地方。 / p>
答案 1 :(得分:1)
除了Mark Setchell指出的差异(使用bash -c
运行单独的命令而不保持环境变化)之外,还有另一个重要的差异:使用bash <file
从文件中重定向标准输入(这就是{{ 1}}),这意味着(几乎)所有输入(不仅仅是命令)都是从文件而不是从终端读取的。例如,假设您将其作为文件:
<
如果使用read -p "Enter some text: " input
echo "You entered: $input"
echo "No, really, you entered: $input"
运行这些命令,则bash <file
命令将从文件而不是终端读取:
read
如果不清楚此处发生的情况,我将详细解释。 $ bash <script.sh
No, really, you entered: echo "You entered: $input"
以脚本文件作为输入。它读取第一行,并将其作为命令执行。那是bash
命令,因此它从文件中读取一行 (获取文件的第二行),并将其分配给变量read
。然后,它读取下一行(第三行)并再次将其作为命令执行。
另一方面,让我们与input
逐行尝试:
bash -c
这里发生的是马克所描述的。第一条命令已从终端成功读取,并将输入分配给变量$ bash -c 'read -p "Enter some text: " input'
Enter some text: Hey, look, it's actually letting me enter something here!
$ bash -c 'echo "You entered: $input"'
You entered:
$ bash -c 'echo "No, really, you entered: $input"'
No, really, you entered:
。但是第二和第三个命令具有新环境,没有设置该变量,因此将其打印为空白。
这给我带来了一种更好的方式来运行文件中的命令:使用input
运行(注意缺少bash file
)。这告诉bash打开文件并从中读取命令,但没有其他内容。标准输入不受影响,因此脚本中的交互式命令可以像通常一样从终端读取:
<
但是还有一种更好的方法:添加一个shebang行,使脚本可执行,然后使用$ bash script.sh
Enter some text: Hey, look, it's actually letting me enter something here!
You entered: Hey, look, it's actually letting me enter something here!
No, really, you entered: Hey, look, it's actually letting me enter something here!
运行它。这样一来,人们就可以运行脚本而不必担心该脚本使用哪种脚本语言。这被认为是运行脚本的正常方法,这是有原因的:它通常比其他方法要好。