在 bash 脚本中重定向 stdout 和 stderr

在 bash 脚本中重定向 stdout 和 stderr

我有以下脚本(行号仅供参考):

#!/bin/bash

1-  for version in `ls -al ./atk/ | grep ^d | grep -Ev '\.$' | awk -F' ' '{print $8}'`
2-      do
3-          grep $version ./atk/versions #&>/dev/null <--(first ran with this comment out)
4-          if [ $? -ne 0 ]
5-              then
6-                  printf '%-15s\n' "$version"
7-          fi
8-      done

如果我按原样运行它,第 1 行会将以下内容发送到屏幕:(我真的不想要这个,希望 stdout/stderr 转到/dev/null,但稍后会详细介绍)

aaaaa--------
bbbbb       |
ccccc       |
ddddd       |------------ wil be stored in the version variable
eeeee       |
fffff       |
ggggg--------

$version第 2 行将在包含以下内容的“版本”文件中查找:

12345
aaaaa
67890
ccccc
09876
fffff

如果$version在“versions”文件中找不到,则将 $versions 打印到标准输出。

输出应如下所示:

bbbbb
ddddd
eeeee
ggggg

如何让第 1 行将其输出发送到/dev/null,然后让第 3 行将其输出发送回 stdout 和 stderr?

奇怪的是,如果我取消第 3 行末尾的注释,尽管 stdout 和 stderr 重定向到/dev/null! ,但一切正常。

我尝试了以下方法:

for version in `ls -al ./atk/ | grep ^d &>/dev/null | grep -Ev '\.$' | awk -F' ' '{print $8}'` &>/dev/null

它不仅抑制了我不想从第 1 行看到的输出,而且还抑制了即使在修改代码后我确实想看到的第 3 行的输出:

for version in `ls -al ./atk/ | grep ^d | grep -Ev '\.$' | awk -F' ' '{print $8}'` &>/dev/null
    do
        exec &>/dev/tty  ++++++++++++++ trying to reset stdout and stderr back to the origal setting
        grep $version ./atk/versions #&>/dev/null

再说一次,当我明确要求将所有输出发送到 时,为什么没有注释的第 3 行会起作用/dev/null

答案1

在第 1 行,反引号中的命令发送其标准输出for...循环。除非某个命令出现错误(例如,ls可能会抱怨缺少目录路径),否则它不会向屏幕写入任何内容。

grep3 行确实写入标准输出, 尽管。也许您想要-q安静模式的标志。

我试图了解您实际上想要做什么,因为我认为它可能可以更简单地处理:

for item in atk/*
do
    test -d "$item" && echo "${item/*\/}" | grep -Fvf atk/versions
done

顺便说一句,使用反引号进行命令插值不再被认为是良好的编码风格。您最好使用该$( ... )构造。例如for version in $( ls ... awk )

相关内容