我们建议,在 bash 脚本中,我们不应该解析 ls 的输出
上面链接的网页推荐的代码如下:
# Good!
for f in *; do
[[ -e $f ]] || continue
...
done
Run Code Online (Sandbox Code Playgroud)
或用文件名填充数组
myfiles=( ~/* )
Run Code Online (Sandbox Code Playgroud)
但是当我查看这些示例并了解 bourne shell 通常如何处理未加引号的字符串时,我的感觉是,如果我在包含空格的文件名上使用此代码,则 glob 会爆炸文件上的每个 - 空格分隔 - 单词。例如,如果我有以下目录
$ ls -1
a file I downloaded from the net.pdf
apple.sh
hello world.txt
Run Code Online (Sandbox Code Playgroud)
我运行这个
for file in *
do printf "%s\n" "$file"
done
Run Code Online (Sandbox Code Playgroud)
我期待未引用的字符串行为。例如
a
file
I
downloaded
from
the
net.pdf
apple
hello
world
Run Code Online (Sandbox Code Playgroud)
但我得到的是正确的行为
a file I downloaded from the net.pdf
apple
hello world
Run Code Online (Sandbox Code Playgroud)
数组类似
myfiles=( * )
declare -p myfiles
declare -a myfiles='([0]="a file I downloaded from the net.pdf" [1]="apple" [2]="hello world")'
Run Code Online (Sandbox Code Playgroud)
我的问题是这是为什么?
是不是因为 glob 扩展是在分词后完成的?(以便这些类型的文件操作产生正确的输出?)
文件名扩展发生在分词后
https://www.gnu.org/software/bash/manual/html_node/Shell-Expansions.html#Shell-Expansions
展开的顺序是:大括号展开;波浪号扩展、参数和变量扩展、算术扩展和命令替换(以从左到右的方式完成);分词;和文件名扩展。