Bashで次のようにコマンドを実行したいとしましょう。
/bin/bash -c "ls -l"
Bashのマニュアルページによると、次のように実行することもできます。
# don't process arguments after this one
# | pass all unprocessed arguments to command
# | |
# V V
/bin/bash -c ls -- -l
しかし、うまくいかないようです(無視されるようです)。私が何か間違っているのか、それともマニュアルページを間違って解釈しているのでしょうか?
男性に関する関連引用:
-c オプションがある場合は、文字列からコマンドを読み込みます。文字列の後にパラメータがある場合は、$ 0から始まる位置パラメータに割り当てられます。
そして
A - オプションの終わりを示し、追加のオプション処理を無効にします。 - 以降のすべての引数はファイル名と引数として扱われます。
答え1
マニュアルページの解釈が正しくありません。まず、オプションの終わりを示す部分は、やりたいこと--
には関係ありません。-c
その時点から、残りのコマンドラインは上書きされ、bashのオプション処理を経なくなりました。つまり、--
bashでオプションの終わりの表示として扱われるのではなく、コマンドに渡されるということです。
2番目のエラーは、追加の引数がコマンドに引数として渡されず、開始されたシェルプロセスに位置引数として割り当てられることです。したがって、実行したい操作は次のいずれかで行うことができます。
/bin/bash -c 'echo "$0" "$1"' foo bar
/bin/bash -c 'echo "$@"' bash foo bar
最初の場合は echo 引数が明示的に渡され$0
、$1
2 番目の場合は"$@"
「$0 を除くすべての位置引数」に一般拡張が使用されます。この場合、使用するものを渡す必要があることに注意してください$0
。私は「bash」を選びました。なぜならこれは$0
一般的ですが、他のものも可能だからです。
これを行う理由は、指定した引数をリストされたコマンドに直接渡すよりも次のようになります。文書に「コマンドS文字列から""(複数形)を読みます。つまり、このプログラムを使用すると、次のことができます。
/bin/bash -c 'mkdir -p -- "$1" && cd -P -- "$1" && touch -- "$2"' bash dir file
ただし、元の目標を達成するためのより良い方法は、次のものをenv
代わりに使用することですbash
。
/usr/bin/env -- "ls" "-l"
シェルが提供する機能が必要ない場合、使用する理由はありません。env
この場合、より速く、簡単で、入力が少なくなります。また、シェルメタ文字やスペースを含むファイル名を安全に処理できることを確認するために、あまりにも懸命に考える必要はありません。
答え2
あなたの目標が何であるかはわかりませんが、ただ構築したい場合ルーブゴールドバーグマシン– 「非常に単純な作業を非常に複雑な方法で実行するために、意図的に過度に設計された、または過度に設計されたデバイス、発明、デバイス、またはデバイス」 – 次に、試してみてください。
sh -c 'ls $0' -l
または
sh -c 'ls $1' supercalifragilisticexpialidocious -l
でも
sh -c 'ls -$0' l
これらのタスクがどのように機能するかを理解できるはずです。神のオタクの答え。 〜のように デリックマハルコメント、スクリプトパラメータ(次のコマンド文字列 -c
)は、二重引用符ではなく一重引用符で囲む必要があることを強調する必要があります。それ以外の場合、親シェル(上記のコマンドラインを入力した場合)は、親シェルのコンテキストでスクリプトパラメータの位置引数を解析します。例えば、
$ set -- The quick brown fox
$ sh -c 'echo "$0" "$1"' foo bar baz
foo bar
$ sh -c "echo '$0' '$1'" foo bar baz
bash The
答え3
それはすべてよりも簡単で、あなたはかなり近いです。
コマンド全体が単一の文字列として渡されるようにスペースをエスケープします。スクリプトは次のとおりです。
bash -c "ls\ -l\ $@"
エスケープされていないスペースで区切って追加のコマンドを追加できます。
# ↓ unescaped
bash -c "cd\ ~/junk ls\ -l\ $@"
# ↑↑ ↑↑ ↑↑ escaped
junk
このコマンドでは、との間のスペースはls
エスケープされていない唯一のスペースであるため、2つのコマンドを区別するのに役立ちます。