避免因未扩展的星号而导致的错误

hig*_*guy 20 bash wildcards for

在 bash 中,我经常使用 for 循环,如下所示

for file in *.type; do 
  sommecommand "$file"; 
done;
Run Code Online (Sandbox Code Playgroud)

对所有匹配的文件执行操作*.type。如果在工作目录中没有找到具有此结尾的文件,则星号不会展开,通常我会收到一条错误消息,指出 somecommand 没有找到该文件。我可以立即想到几种方法来避免这个错误。但是添加一个条件似乎不是很优雅。有没有一种简短而干净的方法来实现这一目标?

Gil*_*not 23

是的,运行以下命令:

shopt -s nullglob
Run Code Online (Sandbox Code Playgroud)

它将使匹配无效并且不会触发任何错误。

  • 如果您希望默认使用此行为,请在您的 ~/.bashrc
  • 如果您想在 POSIX shell 中检测空 glob,请尝试

    for i in *.txt; do
      [ "$i" = '*.txt' ] && [ ! -e '*.txt' ] && continue
    done
    
    Run Code Online (Sandbox Code Playgroud)

http://mywiki.wooledge.org/NullGlob


Sté*_*las 8

对于没有选项的 shell,通常的技术nullglob

set -- [*].type *.type
case $1$2 in
  '[*].type*.type') shift 2;;
  *) shift
esac
for file do
  cmd  -- "$file"
done
Run Code Online (Sandbox Code Playgroud)

额外的内容是为了涵盖当前目录中[*].type调用一个文件的情况。*.type

现在,如果您想包含点文件,那就变得更加复杂

我相信这项技术是几年前由 Laura Fairhead 在 usenet 上创造的。


Chr*_*own 7

在 bash 中,shopt -s nullglob如果没有匹配项,您可以使用扩展为空数组。

在没有 的 POSIX shell 中nullglob,您可以通过将传递的文件名[ -e "$file" ] || [ -L "$file" ] || continue作为for循环的第一部分来检查传递的文件名是否实际存在来避免此问题。

  • 请注意,它并不严格等效,因为对于不可访问的文件或作为不可访问或不存在文件的符号链接的文件,“[ -e”将返回 false。 (2认同)
  • @dubiousjim,`mkdir -px/{a,b} && chmod 444 x && echo x/* && [ -ex/a ]`。x/a 不可访问,但由于 x 可读,x/* 将扩展。 (2认同)