27

在 bash 中,如果你这样做:

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

你会发现array现在有一个元素,,"/tmp/empty/*"而不是你想要的零。值得庆幸的是,可以通过使用打开 nullglob shell 选项来避免这种情况shopt -s nullglob

但是 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而死。除了等待奥斯汀组导入 ksh93 语法,还有吗?

4

5 回答 5

17

完成后取消设置:

shopt -u nullglob

并且正确地(即存储先前的状态):

shopt -u | grep -q nullglob && changed=true && shopt -s nullglob
... do whatever you want ...
[ $changed ] && shopt -u nullglob; unset changed
于 2012-02-03T15:13:43.260 回答
12

mapfileBash 4 中,您可以使用以下内容从子 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
  • 使用打印文件名时,请务必使用 glob./*而不是bare*echo
  • 不适用于文件名中的换行符:(正如derobert指出的那样

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

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

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

于 2013-12-14T07:49:06.547 回答
7

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

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

... 做你想做的 ...

$nullglob ; unset nullglob
于 2016-01-22T22:53:12.570 回答
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

于 2012-02-03T14:02:05.660 回答
1

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

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

VAR=**/*.mp3(N)

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

于 2016-10-27T01:34:38.950 回答