2016-06-07 29 views
2

我正在编写一个shell脚本,用于重定向程序的STDOUTSTDERR输出。重定向的目的地是一个变量。通常,目标是一个文件,在这种情况下,以下工作正常。支持FD号码和文件名参数化重定向

simple_redirect() 
{ 
    myfunc=$1 
    myfile=$2 

    myfunc &>myfile 
} 
simple_redirect ls text.txt 

不过,有时我不想重定向到一个文件,但是要打印到STDOUT像正常。 如果myfile&1STDOUT,我得到以下错误: $myfile: ambiguous redirect

如果我运行命令 ls &>&1,我看到:parse error near '&'

我想通过分别重定向STDOUTSTDERR来解决这个问题:ls 1>&1 2>&1。不过,我更喜欢这个选项,因为我不得不重复使用变量,而且它的可读性较差。有没有更简单的方法来做到这一点?

+0

哪**精确**壳?不只是哪个shell,而是哪个* release *? POSIX根本不指定'&>',并且在bash重定向的右侧使用具有FD编号的变量的能力是最近的(4.x系列)扩展。 –

+0

顺便说一句,'&>&1'做的是'2>&1'不?根据定义,'1&1'完全是多余的,毕竟stdout * already *支持标准输出。 –

+0

也许你的意思是'&>“$ myfile”',顺便说一下?这与'&> myfile'完全不同。 –

回答

1

如果你正在使用bash 4.1或更高版本,下面的工作:

redirect_to() { 
    local myfile=$1; shift 
    case $myfile in 
    -) "[email protected]" ;; 
    "&"*) "[email protected]" >&${myfile#"&"} 2>&1 ;; 
    *) "[email protected]" >"$myfile"  2>&1 ;; 
    esac 
done 

redirect_to -   ls -l foo.d/ # no redirection 
redirect_to &2   ls -l foo.d/ # redirection to FD 2 
redirect_to foo.list ls -l foo.d/ # redirection to foo.list 
redirect_to /dev/stdout ls -l foo.d/ # consider doing this anyhow 

>&$foo是一个bash 4.1扩展,它允许一个变量被用来提供一个文件描述符数 - 在此之前,您需要使用>/dev/fd/${foo#"&"}(如果您的操作系统提供了它们;考虑到问题上的标记,这应该是一个普遍安全的假设)。


如果你没有的bash 4.1或更高版本(特别是如果你的目标POSIX SH,而不是完全的bash),你不能没有eval实施>&$foo选项 - 原始这has substantial security caveats - - 和使用/dev/stdout/dev/stderr/dev/fd/1,最好等

为了与旧版本的bash可能是这个样子的安全地这样做,用printf %q消毒文字形参和%d确保文件描述符只能是数字:

"&"*) printf -v cmd_str '%q ' "[email protected]" 
     printf -v redir_suffix '>&%d' "${myfile#"&"}" 
     eval "$cmd_str $redir_suffix 2>&1" ;;