zsh:如何将 stderr 重定向到 /dev/null?

问题描述

我有一个小功能可以让我激活我的 python 虚拟环境,对于不同的存储库,它有时是隐藏的 (.venv),有时不是 (venv)。我无法抑制 stderr。

这是我的小函数(它存在于~/.zshrc中)

function venv {
    source `ls -a $PWD/*/bin/activate` > /dev/null
    if [[ $? -ne 0 ]] 
    then
        source `ls -a $PWD/.*/bin/activate` 
    fi
}

只存在 $PWD/*/bin/activate$PWD/.*/bin/activate 之一,我想忽略不存在的那个,没有错误

问题是这一行

ls -a $PWD/*/bin/activate 2>&1 /dev/null

给出终端输出

zsh: no matches found: /home/jokea/code/flora/*/bin/activate

我的理解是 2>&1 /dev/null 应该同时抑制 stderr 和 stdout。那么为什么它不起作用?

我已经尝试了我能找到的所有其他变体(>>>&>>& 等),但它仍然打印到终端。如何使函数的所有输出静音?

解决方法

这里有两件事让我烦恼:

ls -a $PWD/*/bin/activate 2>&1 /dev/null

重定向的顺序不正确(您重定向 std 输出中的错误)并且 /dev/null 没有以流重定向为前缀。

您应该首先将 std 输出重定向到 /dev/null,然后将 std 错误重定向到与 std 输出相同的流(即 /dev/null):

ls -a $PWD/*/bin/activate > /dev/null 2>&1
,

使用其他答案并没有让我完全明白,但根据 davidxxx 和 rowboat 的建议(感谢这些),我把这个:

function venv {
    setopt +o nomatch
    ls -a $PWD/.*/bin/activate > /dev/null 2>&1
    if [[ $? -eq 0 ]] 
    then
        source `ls -a $PWD/.*/bin/activate` > /dev/null 2>&1 
    else
        ls -a $PWD/*/bin/activate > /dev/null 2>&1
        if [[ $? -eq 0 ]]  
        then   
           source `ls -a $PWD/*/bin/activate` > /dev/null 2>&1  
        else   
           echo "There's no Virtual Environment in $PWD"     
        fi
    fi
}

诚然,这有点垃圾,但它有效。我现在可以毫无错误地设置虚拟环境。

,

在我看来,在 zsh 通配符 * 扩展中可能并不总是考虑 stderr 重定向。

我常用的更清洁的解决方案是这样的:

find . -maxdepth 2 -name activate -type f -print |
  grep /bin/ |
  head -1 |
  while read script
  do source "$script"
  done