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


16

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

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

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

Answers:


20

是的,运行以下命令:

shopt -s nullglob

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

  • 如果默认情况下您想要这种行为,请在 ~/.bashrc
  • 如果要在POSIX shell中检测到空的glob,请尝试

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

参见http://mywiki.wooledge.org/NullGlob


1
请注意,实际上可能有一个名为的文件*.txt。值得检查文件是否存在。
克里斯·

帖子进行了相应的编辑。
吉尔斯·奎诺

@ChrisDown请注意,此处使用与您的答案相同的评论(由于break而不是,可能会导致更严重的后果continue)。
斯特凡Chazelas

6

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

在没有的POSIX Shell中nullglob,可以通过[ -e "$file" ] || [ -L "$file" ] || continuefor循环的第一部分作为检查对象来检查是否确实存在要传递的文件名,从而避免此问题。


1
请注意,这将不是严格等效的,因为[ -e对于无法访问的文件或作为不可访问或不存在的文件的符号链接的文件将返回false。
斯特凡Chazelas

@StephaneChazelas,让有关符号链接的观点得到承认。但是,“不可访问的文件”对您有什么想法?即使我chmod 0 the_file[ -e the_file ]还是判断为真,所以它必须是别的东西。
dubiousjim 2012年

1
提交编辑以处理损坏的符号链接。希望没事。
dubiousjim 2012年

2
@dubiousjim ,mkdir -p x/{a,b} && chmod 444 x && echo x/* && [ -e x/a ]。x / a无法访问,但由于x是可读的,x / *将扩展。
斯特凡Chazelas

@StephaneChazelas,太好了,谢谢您的解释。
dubiousjim 2012年

4

对于没有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上提出的。


0

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

这样可以for从方程式中完全消除循环和外壳的球状变形。find会在-exec每场比赛中执行一次命令,如果没有比赛,它将永远不会执行。该-maxdepth 0指示找到不递归到指定路径参数的子目录(.在这种情况下)。

不利之处在于,它涉及另一个应用程序,尽管实际上存在于每个Linux系统(可能还有大多数Unix)上。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.