在 zsh 中,如何在 for 或 foreach 循环内将 stderr 重定向到 /dev/null?

在 zsh 中,如何在 for 或 foreach 循环内将 stderr 重定向到 /dev/null?

我正在尝试在 bash 中完成一些简单的事情:在文件夹中查找文件,如果存在则查找它们(如果不存在文件则不输出)。

在 Bourne Shell 中,操作方法如下:

  如果 [ -d /etc/profile.d ]; 那么
      对于 `ls -1 /etc/profile.d/*.sh 2> /dev/null` 中的 f;执行
          .$f
      完毕

我是 zsh 新手,无法使用等效功能。我做错了什么?

如果 [[ -d "/etc/zsh.d" ]]; 那么
    对于文件(ls -1 /etc/zsh.d/*.zsh 2> /dev/null);执行
        源$文件
    完毕

失败:parse error near '>'

我尝试过许多变体,但无法让它像 sh/bash 等效版本那样流畅。就好像重定向在子 shell 中并不总是有效一样。

答案1

在后来向 zsh 用户邮件列表发送了一封电子邮件后,我得到了该问题的近乎理想的解决方案:

如果 [[ -d "/etc/zsh.d" ]]; 那么
  对于 /etc/zsh.d/*.zsh(N) 中的 f;执行
    来源 $f
  完毕

(N) 告诉 zsh 为该模式设置 NULL_GLOB 选项。当未找到匹配项时,glob 将扩展为空字符串,而不是抛出错误。在 zsh 中,对空扩展的 for 循环不执行任何操作,这正是我们在此处想要的行为。

答案2

解析ls不是一个好主意

相反,你可以使用 shell 通配符来获取文件列表:

if [[ -d "/etc/zsh.d" ]]; then
  for f in /etc/zsh.d/*.zsh; do
    source $f
  done
fi

至于重定向,我不确定它在您的例子中的目的是什么,但是如果您使用此方法,那么 shell 可能会抛出错误,而不是,因此在循环ls之后执行重定向。donefor

答案3

我希望你明白几乎所有的 sh 语法在 zsh 中都能正常工作?

# Check dir exists then that there are files in it (silently!)
# If there are no .zsh files in /etc/zsh.d then an empty argument
# is passed to for, which then simply skips the loop

if [ -d /etc/zsh.d ]; then
    for file in $(find /etc/zsh.d/ -name '*.zsh'); do
        source $file
    done
fi

由于您使用的是登录脚本,因此我已尝试使其尽可能快。

这对整个伯恩家族来说应该都有效。

相关内容