在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语法,还有吗?

最佳答案

使用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)
    

    但是到这一点,遵循其他答案之一的建议可能会更简单。

    09-04 00:43