为什么 bash 将 .* 转换为当前目录中的隐藏文件列表以及如何防止它这样做?

为什么 bash 将 .* 转换为当前目录中的隐藏文件列表以及如何防止它这样做?
# list=(`echo ".*"`)
# for item in ${list[@]}; do echo "$item"; done;
.
..
.DS_Store
.git
.gitignore
.tox
.toxrc

在上面的代码中,我尝试在 bash 中将字符串写入.*数组中,但这样做后,“.*”将转换为当前目录中的完整文件/目录列表。我怎样才能阻止 bash 这样做呢?

答案1

list=(`echo ".*"`)

在上面,命令替换周围没有引号,因此生成的输出会受到分词和通配符的影响。

for item in ${list[@]}; do echo "$item"; done;

另外,在这里,你没有引号${list[@]},所以再次,它会受到分词和通配符的影响。 (如果您在作业中添加引号,或者任何匹配的文件名包含空格或通配符,这将很重要......)

如果您只想要文字字符串.*,请使用list=(".*")for item in "${list[@]}"; ...。如果要使用命令替换,请在其两侧加上引号,即"$(somecmd)".

也可以看看:

答案2

man bash,在选项下set

-f      Disable pathname expansion.

所以问题

set -f

禁用通配符,然后

set +f

重新启用正常的通配行为。


手册页中稍长的相关摘录:

路径名扩展

分词后,除非-F选项已设置,巴什扫描每个单词中的字符 *,, 和[。如果出现这些字符之一,则该单词被视为一种模式,并替换为与该模式匹配的按字母顺序排序的文件名列表。

答案3

反引号中的部分echo …产生(不带引号的)字符串.*,随后由 BASH 扩展。如果您不希望“.*”扩展到文件列表,只需使用list=(".*").但是,我看不出对这样一个数组的后续迭代有什么好处。

相关内容