为什么文件 glob 不受分词的影响?

为什么文件 glob 不受分词的影响?

我们建议,在 bash 脚本中,我们不应该解析 ls 的输出

上面链接的网页推荐如下代码:

# Good!
for f in *; do
    [[ -e $f ]] || continue
    ...
done

或用文件名填充数组

myfiles=( ~/* )

但是,当我查看这些示例,并了解 bourne shell 一般如何处理不带引号的字符串时,我的感觉是,如果我在包含空格的文件名上使用此代码,则 glob 将爆炸文件上的每个(空格分隔的)单词。例如如果我有以下目录

$ ls -1  
a file I downloaded from the net.pdf
apple.sh
hello world.txt

我运行这个

for file in *
    do printf "%s\n" "$file"
done

我期待未加引号的字符串行为。例如

a
file
I
downloaded
from
the
net.pdf
apple
hello
world

但我得到的是正确的行为

a file I downloaded from the net.pdf
apple
hello world

与数组类似

myfiles=( * )
declare -p myfiles
declare -a myfiles='([0]="a file I downloaded from the net.pdf" [1]="apple" [2]="hello world")'

我的问题是这是为什么?
是因为分词后进行了全局扩展吗? (以便这些类型的文件操作产生正确的输出?)

答案1

文件名扩展发生在分词之后

https://www.gnu.org/software/bash/manual/html_node/Shell-Expansions.html#Shell-Expansions

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

答案2

[[ -e $f ]]是一个特例。[[是保留字;之间[[]]不同的规则都有效。其中之一是不执行分词。

相关内容