在 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
答案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 0
find 不要递归到指定路径参数的子目录(.
在本例中为 )。
缺点是它涉及另一个应用程序,尽管几乎每个 Linux 系统上都存在这个应用程序(也可能是大多数 Unix)。