有没有一种简单的方法为一个 glob 设置 nullglob
在 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 一起消失。除了等待Austin组导入ksh93语法之外,还有吗?
In bash, if you do this:
mkdir /tmp/empty
array=(/tmp/empty/*)
you find that array
now has one element, "/tmp/empty/*"
, not zero as you'd like. Thankfully, this can be avoided by turning on the nullglob shell option using shopt -s nullglob
But nullglob is global, and when editing an existing shell script, may break things (e.g., did someone check the exit code of ls foo*
to check if there are files named starting with "foo"?). So, ideally, I'd like to turn it on only for a small scope—ideally, one filename expansion. You can turn it off again using shopt -u nullglob
But of course only if it was disabled before:
old_nullglob=$(shopt -p | grep 'nullglob
makes me think there must be a better way. The obvious "put it in a subshell" doesn't work as of course the variable assignment dies with the subshell. Other than waiting for the Austin group to import ksh93 syntax, is there?
)
shopt -s nullglob
array=(/tmp/empty/*)
eval "$old_nullglob"
unset -v old_nullglob
makes me think there must be a better way. The obvious "put it in a subshell" doesn't work as of course the variable assignment dies with the subshell. Other than waiting for the Austin group to import ksh93 syntax, is there?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
完成后取消设置:
并且正确(即存储以前的状态):
Unset it when done:
And properly (i.e. storing the previous state):
使用 Bash 4 中的
mapfile
,您可以从子 shell 中加载数组,如下所示:mapfile array
<(shopt -s nullglob; for f in ./*; do echo "$f"; done)
。完整示例:echo
打印文件名时,请务必使用./*
进行 glob,而不是裸露的*
如果您需要处理文件名中的换行符,则必须执行更详细的操作:
但到目前为止,遵循这一点可能会更简单其他答案之一的建议。
With
mapfile
in Bash 4, you can load an array from a subshell with something like:mapfile array < <(shopt -s nullglob; for f in ./*; do echo "$f"; done)
. Full example:./*
instead of a bare*
when usingecho
to print the file nameIf you need to handle newlines in the filename, you will have to do the much more verbose:
But by this point, it may be simpler to follow the advice of one of the other answers.
这比你原来的建议好一点:
......做你想做的事......
This is just a tiny bit better than your original suggestion:
... do whatever you want ...
这可能接近你想要的;事实上,它需要执行一个命令来扩展 glob。
我们没有在子 shell 中设置
array
,而是使用$()
创建一个子 shell,其输出由array
捕获。This may be close to what you want; as is, it requires executing a command to expand the glob.
Instead of setting
array
in the subshell, we create a subshell using$()
whose output is captured byarray
.这是我发现的最简单的解决方案:
例如,要将文字
**/*.mp3
扩展为仅用于特定变量的 glob,您可以使用Source: https://unix.stackexchange.com/a/204944/56160
This is the simplest solution I've found:
For example, to expand the literal
**/*.mp3
into a glob for only a particular variable, you can useSource: https://unix.stackexchange.com/a/204944/56160