有没有一种简单的方法可以为一个glob设置nullglob

时间:2012-02-03 09:02:10

标签: bash glob

在bash中,如果你这样做:

mkdir /tmp/empty
array=(/tmp/empty/*)

您发现array现在有一个元素"/tmp/empty/*",而不是您想要的零。值得庆幸的是,使用shopt -s nullglob

打开nullglob shell选项可以避免这种情况

但是nullglob是全局的,并且当编辑现有的shell脚本时,可能会破坏事物(例如,有人检查ls foo*的退出代码以检查是否存在以“foo”开头的文件?)。因此,理想情况下,我只想在小范围内启用它 - 理想情况下,一个文件名扩展。您可以使用shopt -u nullglob再次将其关闭但当然只有在之前被禁用时才会将其关闭:

old_nullglob=$(shopt -p | grep 'nullglob$')
shopt -s nullglob
array=(/tmp/empty/*)
eval "$old_nullglob"
unset -v old_nullglob

让我觉得必须有更好的方法。明显的“把它放在子shell中”不起作用,因为变量赋值与子shell一起消失。除了waiting for the Austin group导入ksh93语法之外,还有吗?

5 个答案:

答案 0 :(得分:15)

完成后取消设置:

shopt -u nullglob

正确(即存储以前的状态):

shopt -u | grep -q nullglob && changed=true && shopt -s nullglob
... do whatever you want ...
[ $changed ] && shopt -u nullglob; unset changed

答案 1 :(得分:9)

在Bash 4中使用mapfile,您可以从子shell加载数组,例如:mapfile array < <(shopt -s nullglob; for f in ./*; do echo "$f"; done)。完整的例子:

$ shopt nullglob
nullglob        off
$ find
.
./bar baz
./qux quux
$ mapfile array < <(shopt -s nullglob; for f in ./*; do echo "$f"; done)
$ shopt nullglob
nullglob        off
$ echo ${#array[@]}
2
$ echo ${array[0]}
bar baz
$ echo ${array[1]}
qux quux
$ rm *
$ mapfile array < <(shopt -s nullglob; for f in ./*; do echo "$f"; done)
$ echo ${#array[@]}
0
  • 使用./*打印文件名
  • 时,请务必使用*而不是裸echo
  • 不适用于文件名中的换行符:(正如 derobert
  • 所指出的那样

如果您需要处理文件名中的换行符,则必须执行更详细的操作:

array=()
while read -r -d $'\0'; do
    array+=("$REPLY")
done < <(shopt -s nullglob; for f in ./*; do printf "$f\0"; done)

但就此而言,遵循其他答案之一的建议可能更为简单。

答案 2 :(得分:6)

这比你原来的建议好一点:

local nullglob = $(shopt -p nullglob); shopt -s nullglob

......做你想做的事......

$ nullglob; unset nullglob

答案 3 :(得分:2)

这可能接近你想要的;因此,它需要执行一个命令来扩展glob。

$ ls
file1 file2
$ array=( $(shopt -s nullglob; ls foo*) )
$ ls foo*
ls: foo*: No such file or directory
$ echo ${array[*]}
file1 file2

我们不是在子shell中设置array,而是使用$()创建子shell,其输出由array捕获。

答案 4 :(得分:1)

这是我发现的最简单的解决方案:

例如,要将文字**/*.mp3扩展为仅针对特定变量的glob,您可以使用

VAR=**/*.mp3(N)

来源:https://unix.stackexchange.com/a/204944/56160