web-dev-qa-db-ja.com

「bash -c」に引数を追加します

次のようにBashを介してコマンドを実行するとします。

/bin/bash -c "ls -l"

Bashのmanページによると、次のように実行することもできます。

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

機能していないようです(無視されているようです)。私は何か間違ったことをしていますか、それともマニュアルページを間違って解釈していますか?

人からの関連引用:

-cオプションが存在する場合、コマンドは文字列から読み取られます。文字列の後に引数がある場合、それらは$ 0から始まる定位置パラメーターに割り当てられます。

そして

A-オプションの終了を通知し、それ以降のオプション処理を無効にします。 -の後の引数は、ファイル名と引数として扱われます。

25
Slartibartfast

あなたはmanページを間違って解釈しています。まず、--のオプションの終わりを知らせる部分は、何をしようとしているのかとは無関係です。 -cは、それ以降、コマンドラインの残りの部分を上書きするため、bashのオプション処理はまったく行われなくなります。つまり、--は、オプションマーカーの終わりとしてのbash。

2つ目の間違いは、追加の引数がコマンドの引数として渡されずに、起動されたシェルプロセスの位置パラメータとして割り当てられることです。だから、あなたがやろうとしていることは、次のいずれかとして行うことができます:

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

最初のケースでは、パラメーター$0$1を明示的にエコーし、2番目のケースでは、"$@"を使用して、「$ 0を除くすべての位置パラメーター」と同じように展開します。その場合、$0として使用されるものも渡す必要があることに注意してください。 「bash」を選択したのは、それが通常$0になるためですが、他の方法でも機能します。

この方法で行われる理由としては、リストするコマンドに直接渡す引数を単に渡すのではなく、ドキュメントに「command sは文字列から読み取られる」と記載されていることに注意してください。つまり、このスキームでは次のことが可能です。

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

ただし、元の目標を達成するためのより良い方法は、envではなくbashを使用することです。

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

シェルが提供している機能が必要ない場合は、それを使用する理由はありません。この場合、envを使用すると、より速く、簡単に、入力が少なくなります。また、シェルのメタ文字や空白を含むファイル名を安全に処理できるかどうかを確認する必要はありません。

37
godlygeek

あなたの目的が何であるかはわかりませんが、単に Rube Goldberg machine –を構築しようとしている場合は、意図的に過剰に設計された、または過剰に実行された、仕掛け、発明、デバイスまたは装置です。非常に複雑な方法での非常に単純なタスク」–次に試してください

sh -c 'ls $0' -l

または

sh -c 'ls $1' supercalifragilisticexpialidocious -l

あるいは

sh -c 'ls -$0' l

Godlygeekの答えから、これらがどのように機能するかを理解できるはずです。

3
Scott