是否有一种简单的方法来为一个glob设置nullglob [英] Is there an easy way to set nullglob for one glob

查看:134
本文介绍了是否有一种简单的方法来为一个glob设置nullglob的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在bash中,如果您这样做:

In bash, if you do this:

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

您发现array现在有一个元素"/tmp/empty/*",而不是您想要的零.幸运的是,可以通过使用shopt -s nullglob

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

但是nullglob是全局的,并且在编辑现有的shell脚本时可能会破坏某些内容(例如,是否有人检查了ls foo*的退出代码以检查是否存在以"foo"开头的文件?).因此,理想情况下,我只想在很小的范围内打开它-理想情况下是一个文件名扩展.您可以使用shopt -u 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$')
shopt -s nullglob
array=(/tmp/empty/*)
eval "$old_nullglob"
unset -v old_nullglob

使我认为必须有更好的方法.显然,将其放入子外壳"是行不通的,因为变量赋值当然会随子外壳一起消失.除了正在等待Austin组导入ksh93语法之外,还有吗?

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?

推荐答案

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

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:

$ 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
  • 中指出的换行符

    • Be sure to glob with ./* instead of a bare * when using echo to print the file name
    • Doesn't work with newline characters in the filename :( as pointed out by derobert
    • 如果您需要处理文件名中的换行符,则必须做得更加冗长:

      If you need to handle newlines in the filename, you will have to do the much more verbose:

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

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

      But by this point, it may be simpler to follow the advice of one of the other answers.

      这篇关于是否有一种简单的方法来为一个glob设置nullglob的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆