检测shell脚本的输出流类型

时间:2021-09-05 00:29:18

I'm writing a shell script that uses ANSI color characters on the command line.

我正在编写一个在命令行上使用ANSI颜色字符的shell脚本。

Example: example.sh

示例:example.sh

#!/bin/tcsh
printf "\033[31m Success Color is awesome!\033[0m"

My problem is when doing:

我的问题在于:

$ ./example.sh > out

or

要么

$./example.sh | grep 

The ASCII codes will be sent out raw along with the text, mucking up the output and just generally causing chaos.

ASCII码将与文本一起原始发送,使输出混乱并且通常导致混乱。

I'm interested to know if there is a way to detect this so I could disable color for this special case.

我很想知道是否有办法检测到这一点,所以我可以禁用这种特殊情况的颜色。

I've search the tcsh man pages and the web for a while and have not been able to find anything shell specific yet.

我已经搜索了tcsh手册页和网页一段时间,但还没有找到任何特定的shell。

I'm not bound to tcsh, it's our group standard... but who cares?

我不一定要tcsh,这是我们的团队标准......但谁在乎呢?

Is it possible to detect, inside a shell script, if your output is being redirected or piped?

是否可以在shell脚本中检测输出是否被重定向或管道传输?

4 个解决方案

#1


13  

See this previous SO question, which covers bash. Tcsh provides the same functionality with filetest -t 1 to see if standard output is a terminal. If it is, then print the color stuff, else leave it out. Here's tcsh:

请参阅此前的SO问题,其中包含bash。 Tcsh提供与filetest -t 1相同的功能,以查看标准输出是否为终端。如果是,则打印颜色,否则将其留下。这是tcsh:

#!/bin/tcsh
if ( -t 1 ) then
        printf "\033[31m Success Color is awesome!\033[0m"
else
        printf "Plain Text is awesome!"
endif

#2


6  

Inside a bourne shell script (sh, bask, ksh, ...), you can feed the standard output to the tty program (standard in Unix) which tells you whether its input is a tty or not, by using the -s flag.

在bourne shell脚本(sh,bask,ksh,...)中,你可以通过使用-s标志将标准输出提供给tty程序(Unix中的标准),它告诉你输入是否是tty。 。

Put the following into "check-tty":

将以下内容放入“check-tty”:

    #! /bin/sh
    if tty -s <&1; then
      echo "Output is a tty"
    else
      echo "Output is not a tty"
    fi

And try it:

试试吧:

    % ./check-tty
    Output is a tty
    % ./check-tty | cat
    Output is not a tty

I don't use tcsh, but there must be a way to redirect your standard output to tty's standard input. If not, use

我不使用tcsh,但必须有一种方法将标准输出重定向到tty的标准输入。如果没有,请使用

    sh -c "tty -s <&1"

as your test command in your tcsh script, check its exit status and you're done.

作为tcsh脚本中的测试命令,检查其退出状态,然后就完成了。

#3


3  

The detection of the output stream type is covered in the question detect if shell script is running through a pipe.

检测shell脚本是否正在通过管道检测输出流类型的检测。

Having decided that you are talking to terminal, then you can use tput to retrieve the correct escape codes for the particular terminal you are using - this will make the code more portable.

在确定您正在与终端通信之后,您可以使用tput为您正在使用的特定终端检索正确的转义码 - 这将使代码更具可移植性。

An example script (in bash I am afraid, as tcsh is not my forte) is given below.

下面给出了一个示例脚本(在bash我害怕,因为tcsh不是我的强项)。

#!/bin/bash

fg_red=
fg_green=
fg_yellow=
fg_blue=
fg_magenta=
fg_cyan=
fg_white=
bold=
reverse=
attr_end=

if [ -t 1 ]; then
    fg_red=$(tput setaf 1)
    fg_green=$(tput setaf 2)
    fg_yellow=$(tput setaf 3)
    fg_blue=$(tput setaf 4)
    fg_magenta=$(tput setaf 5)
    fg_cyan=$(tput setaf 6)
    fg_white=$(tput setaf 7)
    bold=$(tput bold)
    reverse=$(tput rev)
    underline=$(tput smul)
    attr_end=$(tput sgr0)
fi

echo "This is ${fg_red}red${attr_end}"
echo "This is ${fg_green}green${attr_end}"
echo "This is ${fg_yellow}yellow${attr_end}"
echo "This is ${fg_blue}blue${attr_end}"
echo "This is ${fg_magenta}magenta${attr_end}"
echo "This is ${fg_cyan}cyan${attr_end}"
echo "This is ${fg_white}white${attr_end}"
echo "This is ${bold}bold${attr_end}"
echo "This is ${reverse}reverse${attr_end}"
echo "This is ${underline}underline${attr_end}"

For more information see "man tput" and "man terminfo" - there are all sorts of escape codes to play with.

有关更多信息,请参阅“man tput”和“man terminfo” - 可以使用各种转义码。

#4


-2  

As far as I know, there is no way to determine the final destination of the output of your shell script; the only thing you can do is provide a switch which allows for suppression of control characters in the output.

据我所知,没有办法确定shell脚本输出的最终目的地;你唯一能做的就是提供一个允许抑制输出中控制字符的开关。

#1


13  

See this previous SO question, which covers bash. Tcsh provides the same functionality with filetest -t 1 to see if standard output is a terminal. If it is, then print the color stuff, else leave it out. Here's tcsh:

请参阅此前的SO问题,其中包含bash。 Tcsh提供与filetest -t 1相同的功能,以查看标准输出是否为终端。如果是,则打印颜色,否则将其留下。这是tcsh:

#!/bin/tcsh
if ( -t 1 ) then
        printf "\033[31m Success Color is awesome!\033[0m"
else
        printf "Plain Text is awesome!"
endif

#2


6  

Inside a bourne shell script (sh, bask, ksh, ...), you can feed the standard output to the tty program (standard in Unix) which tells you whether its input is a tty or not, by using the -s flag.

在bourne shell脚本(sh,bask,ksh,...)中,你可以通过使用-s标志将标准输出提供给tty程序(Unix中的标准),它告诉你输入是否是tty。 。

Put the following into "check-tty":

将以下内容放入“check-tty”:

    #! /bin/sh
    if tty -s <&1; then
      echo "Output is a tty"
    else
      echo "Output is not a tty"
    fi

And try it:

试试吧:

    % ./check-tty
    Output is a tty
    % ./check-tty | cat
    Output is not a tty

I don't use tcsh, but there must be a way to redirect your standard output to tty's standard input. If not, use

我不使用tcsh,但必须有一种方法将标准输出重定向到tty的标准输入。如果没有,请使用

    sh -c "tty -s <&1"

as your test command in your tcsh script, check its exit status and you're done.

作为tcsh脚本中的测试命令,检查其退出状态,然后就完成了。

#3


3  

The detection of the output stream type is covered in the question detect if shell script is running through a pipe.

检测shell脚本是否正在通过管道检测输出流类型的检测。

Having decided that you are talking to terminal, then you can use tput to retrieve the correct escape codes for the particular terminal you are using - this will make the code more portable.

在确定您正在与终端通信之后,您可以使用tput为您正在使用的特定终端检索正确的转义码 - 这将使代码更具可移植性。

An example script (in bash I am afraid, as tcsh is not my forte) is given below.

下面给出了一个示例脚本(在bash我害怕,因为tcsh不是我的强项)。

#!/bin/bash

fg_red=
fg_green=
fg_yellow=
fg_blue=
fg_magenta=
fg_cyan=
fg_white=
bold=
reverse=
attr_end=

if [ -t 1 ]; then
    fg_red=$(tput setaf 1)
    fg_green=$(tput setaf 2)
    fg_yellow=$(tput setaf 3)
    fg_blue=$(tput setaf 4)
    fg_magenta=$(tput setaf 5)
    fg_cyan=$(tput setaf 6)
    fg_white=$(tput setaf 7)
    bold=$(tput bold)
    reverse=$(tput rev)
    underline=$(tput smul)
    attr_end=$(tput sgr0)
fi

echo "This is ${fg_red}red${attr_end}"
echo "This is ${fg_green}green${attr_end}"
echo "This is ${fg_yellow}yellow${attr_end}"
echo "This is ${fg_blue}blue${attr_end}"
echo "This is ${fg_magenta}magenta${attr_end}"
echo "This is ${fg_cyan}cyan${attr_end}"
echo "This is ${fg_white}white${attr_end}"
echo "This is ${bold}bold${attr_end}"
echo "This is ${reverse}reverse${attr_end}"
echo "This is ${underline}underline${attr_end}"

For more information see "man tput" and "man terminfo" - there are all sorts of escape codes to play with.

有关更多信息,请参阅“man tput”和“man terminfo” - 可以使用各种转义码。

#4


-2  

As far as I know, there is no way to determine the final destination of the output of your shell script; the only thing you can do is provide a switch which allows for suppression of control characters in the output.

据我所知,没有办法确定shell脚本输出的最终目的地;你唯一能做的就是提供一个允许抑制输出中控制字符的开关。