支持FD编号和文件名参数化重定向

时间:2016-06-07 16:34:13

标签: linux shell io-redirection

我正在编写一个shell脚本,用于重定向程序的[1,2,3] [1,2,5] [1,4,2] [2,3,1] [2,2,1] [3,7,1] [] [1,1,1] [] [1,2,2] [] [] [] [] [] STDOUT输出。重定向的目标是变量。通常,目标是一个文件,在这种情况下,以下工作正常。

STDERR

但是,有时我不想重定向到文件,但想要像平常一样打印到simple_redirect() { myfunc=$1 myfile=$2 myfunc &>myfile } simple_redirect ls text.txt 。 如果STDOUT myfile&1,则会收到以下错误消息: STDOUT

如果我运行命令 $myfile: ambiguous redirect,我看到:ls &>&1

通过分别重定向parse error near '&'STDOUTSTDERR,我想到了一种解决方法。但是,我更喜欢这个选项,因为我必须重用变量并且它的可读性较差。有更简单的方法吗?

1 个答案:

答案 0 :(得分:1)

如果您使用的是bash 4.1或更新版本,则以下内容将起作用:

redirect_to() {
  local myfile=$1; shift
  case $myfile in
    -)    "$@" ;;
    "&"*) "$@" >&${myfile#"&"} 2>&1 ;;
    *)    "$@" >"$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),则无法在>&$foo之后实施eval选项 - a使用/dev/stdout/dev/stderr/dev/fd/1等的has substantial security caveats最好的原语。

使用旧版本的bash安全地执行此操作可能看起来像这样,使用printf %q来清理文字参数和%d以确保文件描述符只能是数字:

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