2016-06-07 16 views
2

Ich schreibe ein Shell-Skript, das die STDOUT und STDERR Ausgabe eines Programms umleitet. Das Ziel der Weiterleitung ist eine Variable. Normalerweise ist das Ziel eine Datei, in diesem Fall funktioniert das Folgende gut.Unterstützt sowohl FD-Nummer und Dateinamen parametrisierte Umleitungen

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

    myfunc &>myfile 
} 
simple_redirect ls text.txt 

Aber manchmal möchte ich nicht in eine Datei umleiten, sondern STDOUT wie normale drucken möchten. Wenn myfile&1 für STDOUT ist, bekomme ich folgende Fehlermeldung: $myfile: ambiguous redirect

Wenn ich den Befehl ls &>&1 laufen, ich sehe: parse error near '&'.

Ich habe von einer Vermeidung des Problems gedacht, durch STDOUT und STDERR getrennt Umleitung: ls 1>&1 2>&1. Allerdings mag ich diese Option weniger, da ich die Variable wiederverwenden muss und sie weniger lesbar ist. Gibt es einen einfacheren Weg, dies zu tun?

+0

Welche ** präzise ** Shell? Nicht nur welche Shell, sondern welche * Release *? POSIX spezifiziert nicht '&>' überhaupt, und die Fähigkeit, eine Variable mit einer FD-Nummer auf der rechten Seite einer Umleitung in bash zu verwenden, ist eine aktuelle Erweiterung (4.x-Serie). –

+0

BTW, was macht '&> & 1' das' 2> & 1' nicht? '1> & 1' ist komplett redundant, immerhin - stdout * bereits * unterstützt per Definition stdout. –

+0

Vielleicht meinst du '&>" $ myfile "', übrigens? Das ist eine ganz andere Sache als '&> myfile'. –

Antwort

1

Wenn Sie mit bash 4.1 oder höher, wird folgende Arbeiten:

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 ist eine bash 4.1-Erweiterung, die eine Variable eine Dateideskriptor Nummer angeben verwendet werden kann - vor diesem , müssten Sie stattdessen >/dev/fd/${foo#"&"} verwenden (wenn Ihr Betriebssystem sie bereitstellt; vorausgesetzt, dass der Tag in der Frage eine allgemein sichere Annahme ist).


Wenn Sie nicht über bash 4.1 oder neue (und vor allem, wenn Sie POSIX-Targeting sind sh statt bash insgesamt), können Sie die Option >&$foo nicht implementieren können, ohne eval - ein primitiven die has substantial security caveats - - und ist besser mit /dev/stdout, /dev/stderr, /dev/fd/1 usw.

so sicher mit älteren Versionen von bash zu tun könnte etwa so aussehen, printf %q mit wörtlichen Argumente zu sanieren und %d um sicherzustellen, dass die Deskriptordatei nur sein kann numerisch:

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