避免由于未展开的星号而导致的错误

避免由于未展开的星号而导致的错误

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

for file in *.type; do 
  sommecommand "$file"; 
done;

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

答案1

是的,运行以下命令:

shopt -s nullglob

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

  • 如果您希望默认情况下出现此行为,请将该命令添加到您的~/.bashrc
  • 如果你想在 POSIX shell 中检测空 glob,请尝试

    for i in *.txt; do
      [ "$i" = '*.txt' ] && [ ! -e '*.txt' ] && continue
    done
    

http://mywiki.wooledge.org/NullGlob

答案2

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

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

答案3

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

set -- [*].type *.type
case $1$2 in
  '[*].type*.type') shift 2;;
  *) shift
esac
for file do
  cmd  -- "$file"
done

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

现在,如果你想包含点文件,这变得更加复杂

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

答案4

find . -name '*.type' -maxdepth 0 -exec somecommand "{}" ";"

for从方程中完全消除了循环和 shell 的通配符。每次匹配find都会执行-exec一次该命令,如果没有匹配,则永远不会执行。指示-maxdepth 0find 不要递归到指定路径参数的子目录(.在本例中为 )。

缺点是它涉及另一个应用程序,尽管几乎每个 Linux 系统上都存在这个应用程序(也可能是大多数 Unix)。

相关内容