Argumente zu 'bash -c' hinzufügen

22

Angenommen, ich möchte einen Befehl wie folgt über Bash ausführen:

/bin/bash -c "ls -l"

Laut Bash-Manpage könnte ich es auch so ausführen:

#               don't process arguments after this one
#               |   pass all unprocessed arguments to command
#               |   |
#               V   V
/bin/bash -c ls -- -l

außer es scheint nicht zu funktionieren (es scheint ignoriert). Mache ich etwas falsch oder interpretiere ich die Manpage falsch?

Relevante Zitate von Mann:

Wenn die Option -c vorhanden ist, werden Befehle aus der Zeichenfolge gelesen. Befinden sich nach der Zeichenfolge Argumente, werden diese den Positionsparametern zugewiesen, beginnend mit $ 0.

und

A - signalisiert das Ende von Optionen und deaktiviert die weitere Optionsverarbeitung. Alle Argumente nach dem - werden als Dateinamen und Argumente behandelt.

Slartibartfast
quelle

Antworten:

33

Sie interpretieren die Manpage falsch. Erstens ist der Teil über das --Signalisieren des Endes von Optionen für das, was Sie versuchen, irrelevant. Die -cÜberschreibungen der Rest der Befehlszeile von diesem Punkt an, so dass es nicht mehr ist gehen durch alle bash Option Handhabung bei, was bedeutet , dass die --durch auf den Befehl übergeben werden würde, nicht durch bash als Ende der Optionen Marker behandelt.

Der zweite Fehler besteht darin, dass dem gestarteten Shell-Prozess zusätzliche Argumente als Positionsparameter zugewiesen und nicht als Argumente an den Befehl übergeben werden. Das, was Sie versuchen zu tun, könnte folgendermaßen aussehen:

/bin/bash -c 'echo "$0" "$1"' foo bar
/bin/bash -c 'echo "$@"' bash foo bar

Im ersten Fall werden die Parameter mit echo $0und $1explizit übergeben, und im zweiten Fall mit "$@", um so normal wie "alle Positionsparameter außer $ 0" zu expandieren. Beachten Sie, dass wir in diesem Fall auch etwas übergeben müssen, um es verwenden zu können $0. Ich habe mich für "bash" entschieden, da $0dies normalerweise der Fall wäre, aber alles andere würde funktionieren.

Aus diesem Grund müssen Sie nicht nur Argumente direkt an den aufgeführten Befehl übergeben: Beachten Sie, dass in der Dokumentation der Plural "Befehl s werden aus Zeichenfolge gelesen" steht. Mit anderen Worten, dieses Schema ermöglicht Ihnen Folgendes:

/bin/bash -c 'mkdir "$1"; cd "$1"; touch "$2"' bash dir file

Beachten Sie jedoch, dass eine bessere Möglichkeit, Ihr ursprüngliches Ziel zu erreichen, enveher darin besteht, Folgendes zu verwenden bash:

/usr/bin/env -- "ls" "-l"

Wenn Sie keine der von einer Shell bereitgestellten Funktionen benötigen, gibt es keinen Grund, sie zu verwenden. envIn diesem Fall ist die Verwendung schneller, einfacher und erfordert weniger Eingaben. Und Sie müssen nicht so genau nachdenken, um sicherzustellen, dass Dateinamen, die Shell-Metazeichen oder Leerzeichen enthalten, sicher verarbeitet werden.

godlygeek
quelle
3

Ich bin mir nicht sicher, was Ihr Ziel ist, aber wenn Sie einfach versuchen, eine Rube Goldberg-Maschine zu bauen - „eine Erfindung, ein Gerät oder eine Vorrichtung, die absichtlich überarbeitet oder übertrieben wurde, um eine sehr einfache Aufgabe in einer sehr einfachen Weise auszuführen komplizierte Mode “- dann versuchen Sie es

sh -c 'ls $0' -l

oder

sh -c 'ls $1' supercalifragilisticexpialidocious -l

oder auch

sh -c 'ls -$0' l

Sie sollten in der Lage sein zu verstehen, wie diese aus Godlygeeks Antwort funktionieren.

Scott
quelle