2010-08-12 7 views
7

Ich habe versucht, Befehle mit Pipes auszuführen.Wie Skript Befehle von Variablen ausführen?

Grund:

single="ls -l" 
$single 

die als

Pipes erwartet funktioniert:

multi="ls -l | grep e" 
$multi 
ls: |: No such file or directory 
ls: grep: No such file or directory 
ls: e: No such file or directory 

... keine Überraschung

bash < $multi 

$multi: ambiguous redirect 
nächste

versuchen

bash $multi 
/bin/ls: /bin/ls: cannot execute binary file 

Nur

echo $multi > tmp.sh 
bash tmp.sh 

gearbeitet.

Gibt es eine Möglichkeit, komplexere Befehle auszuführen, ohne ein Skript zur Ausführung zu erstellen?

+0

See [BashFAQ/050] (http://mywiki.wooledge.org/BashFAQ/050). –

Antwort

11

Sie demonstrieren den Unterschied zwischen der Shell und dem Kernel.

"ls -l" ist ausführbar durch den Aufruf von System execve(). Sie können man execve für Details, aber das ist wahrscheinlich zu viel Detail für Sie.

"ls -l | grep e" benötigt eine Shell-Interpretation, um die Pipe einzurichten. Ohne eine Shell zu verwenden, ist das '|' Das Zeichen wird in execve() als Argument an ls übergeben. Deshalb sehen Sie die Fehler "Keine solche Datei oder Verzeichnis".

Lösung:

cmd="ls -l | grep e" 
bash -c "$cmd" 
+0

Danke, irgendeine Idee, warum "bash -c" die Ausgabe in einer einzigen Zeile druckt? Ich hätte gerne die gleiche Ausgabe, die manuell über die Befehlszeile eingegeben wurde. – stacker

+0

@stacker Ich glaube nicht, dass das stimmt.Ich bekomme das gleiche Ergebnis wie an der Befehlszeile. Vielleicht gibt dein Grep nur eine einzige Zeile zurück? – bukzor

+0

Dies passierte, weil ich vergessen habe, die Variable in doppelte Anführungszeichen zu setzen. – stacker

-3

wenn Sie Befehle mit Rohren laufen, nur um es auszuführen. Setze den Befehl niemals in eine Variable und versuche ihn auszuführen. führen Sie es einfach

ls -l |grep

Wenn Sie die Ausgabe aufnehmen möchten, verwenden Sie $()

var=$(ls -l |grep ..)

+0

Die Befehle kommen von einem anderen Server und sollten auf dem Zielrechner ausgeführt werden. Daher kann es nicht hart codiert werden. – stacker

+0

siehe http://mywiki.wooledge.org/BashFAQ/050 – ghostdog74

0

Sie benötigen einen heredoc dies richtig zu tun. Als Antwort auf POSIX compliant way to see if a function is defined in an sh script habe ich detailliert beschrieben, wie man ein Skript in eine Variable einliest, es programmatisch für Informationen parst und/oder es bei Bedarf ändert und es dann von einem anderen Skript oder einer anderen Shell-Funktion ausführt. Das ist im Grunde, was Sie zu tun versuchen, und die heredoc macht es möglich, weil es einen Dateideskriptor bietet:

% multi='ls -l | grep e' 
% sh <<_EOF_ 
> ${multi} 
> _EOF_ 
< desired output > 

Das Ihren einfaches Beispiel Fall lösen würde. Siehe meine andere Antwort für mehr.

-Mike

Verwandte Themen