首页 > 解决方案 > bash“if”语句中 glob 的奇怪行为

问题描述

我只是遇到了这种奇怪的行为,但我在任何地方都找不到它的记录。在我完全理解它之前,我很犹豫在我的脚本中使用它。有人可以解释下面的行为吗?

本质上,在我的if声明中,我正在询问当前文件夹中是否存在所有编号的文件,并根据该现实打印一份声明。


如果只有 file1.zip并且file3.zip存在,就会发生这种情况:

> if [ -s file1.zip ] && [ -s file2.zip ] && [ -s file3.zip ] && [ -s file4.zip ]
> then
>   echo All numbers[1-4] exist
> else
>   echo Only numbers[1-4] exist so far
> fi
Only numbers[1-4] exist so far

这是我所期望的。但是,当语句更改为实际匹配语句中的文件名时if,会发生一些有趣的事情:

> if [ -s file1.zip ] && [ -s file2.zip ] && [ -s file3.zip ] && [ -s file4.zip ]
> then
>   echo All file[1-4].zip exist
> else
>   echo Only file[1-4].zip exist so far
> fi
Only file1.zip file3.zip exist so far

现在写出文件名。与此行为一致,当if语句被压缩时,行为重复:

> if [[ -s file[1-4].zip ]]
> then
>   echo All file[1-4].zip exist
> else
>   echo Only file[1-4].zip exist so far
> fi
Only file1.zip file3.zip exist so far

因此,当所有文件都存在时,会发生以下情况:

> if [ -s file1.zip ] && [ -s file2.zip ] && [ -s file3.zip ] && [ -s file4.zip ]
> then
>   echo All numbers[1-4] exist
> else
>   echo Only numbers[1-4] exist so far
> fi
All numbers[1-4] exist
> if [ -s file1.zip ] && [ -s file2.zip ] && [ -s file3.zip ] && [ -s file4.zip ]
> then
>   echo All file[1-4].zip exist
> else
>   echo Only file[1-4].zip exist so far
> fi
All file1.zip file2.zip file3.zip file4.zip exist

但是,在最后一种情况下,由于某种原因,压缩语句的计算结果为,false但所有文件名仍被写出:

> if [[ -s file[1-4].zip ]]
> then
>   echo All file[1-4].zip exist
> else
>   echo Only file[1-4].zip exist so far
> fi
Only file1.zip file2.zip file3.zip file4.zip exist so far

从本质上讲,我的困惑有两个方面:

标签: arraysbashif-statement

解决方案


事实:

  1. [1-4]是一个匹配数字 1 到 4 的全局模式。
  2. 将glob 模式(例如*.txtor [1-4].txt)扩展为单词列表称为文件名扩展
  3. 分词和文件名扩展不在参数内部执行[[ ]]

结论:

  1. file[1-4].zip当一个参数echo扩展为与模式匹配的文件列表时。
  2. [[ -s file[1-4].zip ]]检查一个名为字面意思 file[1-4].zip的文件。IE。它与 相同[[ -s 'file[1-4].zip' ]]

为什么像 numbers[1-4] 这样的术语不展开成单独的术语

当一个 glob 不匹配任何文件时,它不会被扩展并“停留”并且在没有任何更改的情况下传递(除了 when shopt -s nullglob,在这种情况下它会消失)。您没有名为numbers1ornumbers2numbers3or的文件numbers4。创建这样的文件numbers[1-4]并将扩展到它们。

文件的具体名称 (file[1-4].zip)

因为你有file1.zipfile3.zip。删除这些文件,它将保留。

为什么写 if 语句时行为不一致...

因为[[与任何其他命令不同,它由 bash 超级特殊处理。这些是与[[ ]]. 请参阅bash 手册 [[ 表达式.


推荐阅读