为什么“ a =(*)”为数组中的'*'中的每个文件名而不是每个单词分配一个元素?

时间:2019-03-27 18:03:44

标签: arrays bash glob

问题详细信息

假设我们有一个目录,其中包含三个文件:file_1file_2和非常不方便命名的file 3。如果我对filename expansion的理解是正确的,则bash解释字符串的方式

echo *

是因为它看到了(未加引号的)*,并修改了字符串,使其现在可以读取

echo file_1 file_2 file 3

然后,由于没有更多的扩展要执行,bash尝试评估字符串。在这种情况下,它将运行命令echo,并向其传递四个参数:file3file_1和{{1} }。无论如何,输出是相同的:

file_2

但是,在其他情况下,似乎并非如此。例如

$ echo *
> file 3 file_1 file_2
$ echo file 3 file_1 file_2
> file 3 file_1 file_2

但是,如果shell扩展按in the bash documentation所述的方式工作,则它们应该是相同的。

$ arr1=( * ) $ arr2=( file 3 file_1 file_2 ) $ echo ${#arr1} > 3 $ echo ${#arr2} > 4 循环中类似的情况发生:

for

我想念什么?在这种情况下不会发生通气吗?

用例

根据MIT's Hacker Tools的建议,我正在整理一个GitHub存储库以集中我的点文件。我正在编写的脚本有两种用法:

$ for f in *; do echo $f; done
> file 3
> file_1
> file_2
$ for f in file 3 file_1 file_2; do echo $f; done
> file
> 3
> file_1
> file_2

在第一种情况下,./install.sh DOTFILE [DOTFILE [DOTFILE ...]] ./install.sh -a 中的每个命名点文件都被符号链接到我的主目录中的对应点文件;在第二个中,src/config标志提示脚本运行,就像我已经输入每个点文件作为参数一样。

我想出的解决方案是使用两个数组之一-aln -sihfor循环中运行$@ 1 因此,只需分配*FILES=( $@ ),然后运行FILES=( * ) -在我看来,for f in $FILES应该在此分配中中断,如果文件名带有里面的空间。显然*比我聪明,因为它没有,但是我不明白为什么。


1 :显然,您不希望脚本本身在循环中运行,但这很容易用bash子句排除。

1 个答案:

答案 0 :(得分:3)

从您链接到的bash documentation

  

扩展顺序为:大括号扩展;波浪线扩展   参数和变量扩展,算术扩展和命令   替换(以从左到右的方式完成);分词和   文件名扩展。

文件名扩展发生在 分词之后,因此,扩展的文件名本身不再需要进一步的分词。