bash 如何处理不匹配的通配符?
How does bash treat unmatched wildcard?
我学会了 bash 并使用通配符解决了下一个问题:
sergs:~ > ls -1
a.sh
Desktop
Downloads
eclipse
sergs:~ > a=*.sh
sergs:~ > echo $a
a.sh
sergs:~ > a=*.sha
sergs:~ > echo $a
*.sha
如果没有文件匹配 *.sha
模式,为什么 bash
return 模式本身而不是什么都没有?
因此行为打破了这样的逻辑:
for i in /usr/lib/opkg/info/*.postinst; do do_some_logic_with_postinst_file; done
我是否必须明确地检查 /usr/lib/opkg/info/
目录没有任何 *.postinst
文件,在循环之前还是有其他方法可以做到这一点。
除非您打开扩展的 shell 选项 nullglob
,否则未扩展的 glob 字符串会在命令行中逐字返回,如果 glob 扩展失败,returns 则不会产生任何结果。
尽管如此,对于您的用例,通过测试扩展结果是否为文件来检查 glob 扩展在 for 循环中是否成功始终是一个好习惯,即
for file in /usr/lib/opkg/info/*.postinst; do
[ -f "$file" ] || continue
do_some_logic_with_postinst_file
done
条件 [ -f "$file" ]
将检查您的 glob 扩展,即如果有任何 .postinst
文件,则 [ -f "$file" ]
为真。对于未扩展的 glob,条件
[ -f /usr/lib/opkg/info/*.postinst ]
将失败,因为文字字符串 /usr/lib/opkg/info/*.postinst
不是有效文件,并且此 test
命令与布尔 OR ||
一起失败会导致 continue
for
循环的动作。由于 for
循环没有更多的参数要处理,因此循环正常退出。
这样做(使用 -f
反对 glob 字符串)保证是 POSIX 兼容的。不过,对于 bash
具体答案,您可以打开前面提到的选项
# '-s' enables the option
shopt -s nullglob
for file in /usr/lib/opkg/info/*.postinst; do
do_some_logic_with_postinst_file
done
# '-u' disables the option
shopt -u nullglob
一旦您决定使用 nullglob
选项,您可以通过多种方式将其用于 运行 您的功能。例如您可以将所有 glob 结果放入数组类型并检查长度是否有效
shopt -s nullglob
results=(/usr/lib/opkg/info/*.postinst)
if (( ${#results[@]} )); then
printf '%s\n' 'my array is not empty'
for file in "${results[@]}"; do
printf '%s\n' "some action on ${file}"
done
fi
shopt -u nullglob
不使用 nullglob
选项时请小心使用此方法。没有相同的,results=(/usr/lib/opkg/info/*.postinst)
部分仍然可以是非空的,因为文字字符串仍然存储在数组中。
您的 OP 的另一个小附录是永远不要使用变量来保存您的 glob 字符串。因为当变量不加引号扩展并且 glob 扩展成功时,变量的内容会受到 shell 完成的分词的影响,并且包含空格的文件名可能会在您期望时分解为多个条目它不是。
始终使用数组和适当的引用扩展。在 BashFAQ - BashGuide/Arrays 上查看更多关于该主题的优秀读物。
这就是 glob 模式的工作原理(编辑:除非您启用 nullglob
,正如 Inian 指出的那样)。另一种选择可以是
find /usr/lib/opkg/info -name \*.postinst|while read file; do
# do_some_logic_with_postinst_file
done```
我学会了 bash 并使用通配符解决了下一个问题:
sergs:~ > ls -1
a.sh
Desktop
Downloads
eclipse
sergs:~ > a=*.sh
sergs:~ > echo $a
a.sh
sergs:~ > a=*.sha
sergs:~ > echo $a
*.sha
如果没有文件匹配 *.sha
模式,为什么 bash
return 模式本身而不是什么都没有?
因此行为打破了这样的逻辑:
for i in /usr/lib/opkg/info/*.postinst; do do_some_logic_with_postinst_file; done
我是否必须明确地检查 /usr/lib/opkg/info/
目录没有任何 *.postinst
文件,在循环之前还是有其他方法可以做到这一点。
除非您打开扩展的 shell 选项 nullglob
,否则未扩展的 glob 字符串会在命令行中逐字返回,如果 glob 扩展失败,returns 则不会产生任何结果。
尽管如此,对于您的用例,通过测试扩展结果是否为文件来检查 glob 扩展在 for 循环中是否成功始终是一个好习惯,即
for file in /usr/lib/opkg/info/*.postinst; do
[ -f "$file" ] || continue
do_some_logic_with_postinst_file
done
条件 [ -f "$file" ]
将检查您的 glob 扩展,即如果有任何 .postinst
文件,则 [ -f "$file" ]
为真。对于未扩展的 glob,条件
[ -f /usr/lib/opkg/info/*.postinst ]
将失败,因为文字字符串 /usr/lib/opkg/info/*.postinst
不是有效文件,并且此 test
命令与布尔 OR ||
一起失败会导致 continue
for
循环的动作。由于 for
循环没有更多的参数要处理,因此循环正常退出。
这样做(使用 -f
反对 glob 字符串)保证是 POSIX 兼容的。不过,对于 bash
具体答案,您可以打开前面提到的选项
# '-s' enables the option
shopt -s nullglob
for file in /usr/lib/opkg/info/*.postinst; do
do_some_logic_with_postinst_file
done
# '-u' disables the option
shopt -u nullglob
一旦您决定使用 nullglob
选项,您可以通过多种方式将其用于 运行 您的功能。例如您可以将所有 glob 结果放入数组类型并检查长度是否有效
shopt -s nullglob
results=(/usr/lib/opkg/info/*.postinst)
if (( ${#results[@]} )); then
printf '%s\n' 'my array is not empty'
for file in "${results[@]}"; do
printf '%s\n' "some action on ${file}"
done
fi
shopt -u nullglob
不使用 nullglob
选项时请小心使用此方法。没有相同的,results=(/usr/lib/opkg/info/*.postinst)
部分仍然可以是非空的,因为文字字符串仍然存储在数组中。
您的 OP 的另一个小附录是永远不要使用变量来保存您的 glob 字符串。因为当变量不加引号扩展并且 glob 扩展成功时,变量的内容会受到 shell 完成的分词的影响,并且包含空格的文件名可能会在您期望时分解为多个条目它不是。
始终使用数组和适当的引用扩展。在 BashFAQ - BashGuide/Arrays 上查看更多关于该主题的优秀读物。
这就是 glob 模式的工作原理(编辑:除非您启用 nullglob
,正如 Inian 指出的那样)。另一种选择可以是
find /usr/lib/opkg/info -name \*.postinst|while read file; do
# do_some_logic_with_postinst_file
done```