Bash 在zsh中读取文件并运行命令

Bash 在zsh中读取文件并运行命令,bash,zsh,Bash,Zsh,因此,我通常创建包含命令列表的作业文件。然后我就这样执行 cat jobFile | while read a; do $a; done 在bash中总是有效的。然而,我刚刚开始在Mac上工作,它显然使用zsh。这个命令失败,出现“没有这样的文件”等等。我已经通过手动运行几行来测试作业文件,所以应该可以 我发现关于zsh read-in的问题,但它们往往是从变量中读入的,例如$a=('a''b''c')或echo$a 谢谢你的回答 在bash中,不带引号的参数扩展总是进行分词,因此如果a=“f

因此,我通常创建包含命令列表的作业文件。然后我就这样执行

cat jobFile | while read a; do $a; done
在bash中总是有效的。然而,我刚刚开始在Mac上工作,它显然使用zsh。这个命令失败,出现“没有这样的文件”等等。我已经通过手动运行几行来测试作业文件,所以应该可以

我发现关于zsh read-in的问题,但它们往往是从变量中读入的,例如$a=('a''b''c')或echo$a


谢谢你的回答

bash
中,不带引号的参数扩展总是进行分词,因此如果
a=“foo bar”
,则
$a
扩展为两个词,
foo
bar
。作为命令,这意味着使用参数
bar
运行命令
foo

zsh
中,默认情况下不进行分词的参数扩展,这意味着相同的扩展
$a
将生成一个单词
foo bar
,作为要执行的命令的名称

在任何一种情况下,依靠参数扩展来“解析”shell命令都是脆弱的;除了分词之外,扩展还受路径名扩展(globbing)的约束,并且您仅限于使用简单的命令及其参数。不允许使用管道、列表(
&&
|
)或重定向,因为所有内容都将被视为命令名和一系列参数

在这两个shell中,您只需将作业文件视为shell脚本,可以使用
命令在当前shell中执行该脚本:

. jobFile

你为什么要以如此繁琐的方式执行它?假设
jobFile
是一个包含一系列bash命令的文件,您只需将其作为

bash jobFile
zsh jobFile
如果它包含一系列zsh命令,您也可以按如下方式运行它

bash jobFile
zsh jobFile
但是,如果您采用这种方法,我会在作业文件的名称中反映它的用途,即

bash jobFile.bash
zsh jobFile.zsh

而且,如果您编写一个作业文件,使其与任何一个shell兼容,我会将其命名为
jobFile.sh

如果它是一个命令列表,您应该只使用
。作业文件
bash
zsh
中。默认情况下,
zsh
不会对不带引号的参数展开执行分词操作,这可能会让您大吃一惊。如果
a=“foo-bar”
,则
$a
尝试运行名为
foo-bar
的命令,而不是名为
foo
且带有参数
bar
的命令。感谢您的回复@chepner。你能详细说明一下吗?使用
是什么意思。作业文件
?您的意思是删除cat命令并使用。还是别的什么?你能举个例子吗?对不起,我的无礼!您似乎假设文件的每一行都是一个完整的shell命令,在这种情况下,文件本身就是一个shell脚本<代码>。jobFile正是您想要的:它一个接一个地执行每个命令,但是您让shell正确地解析和计算每个命令,而不是依赖于参数扩展技术。@chepner哦,好的,我现在就知道了!谢谢基本上只是直接作为shell脚本执行它。非常感谢。仅仅因为Mac使用
zsh
作为其默认的交互式shell,并不意味着您必须在脚本中使用它。放
#/bin/bash
在脚本的开头,它将使用
bash