xargsコマンドで使用するときにbashがアスタリスク文字を解釈しないのはなぜですか?

xargsコマンドで使用するときにbashがアスタリスク文字を解釈しないのはなぜですか?

私が理解している限り、アスタリスク文字は*Bashで特別な意味を持ち、リテラル文字を印刷するにはアスタリスクをエスケープするか\*()を引用する必要があります("*"または'*'

しかし、次のことを試したとき:

$ seq 3 |  xargs -I *  echo *
1
2
3

*上記の例でBashが説明しないのはなぜですか?ただし、次の例ではこれをワイルドカードとして解釈します(現在のディレクトリのファイルと一致)。

$ seq 3 |  xargs -I*  echo * # no space between -I and *
main.py
main.py
main.py

これに対する論理を説明できますか?

ありがとう

答え1

吹くした最初の例では、アスタリスクを展開します。

現在、ディレクトリにファイルが1つしか含まれていないと仮定すると、main.py次のことが発生します。

$ seq 3 | xargs -I *  echo *
# Expands to:
$ seq 3 | xargs -I main.py echo main.py

echo main.pyこれを行うには、各入力に対してアクションを実行し、そのmain.py入力に置き換える必要があります(したがって-I main.py)。観察した内容は次のとおりです。 3つのテンプレートが、から、にecho main.py変わります。echo 1echo 2echo 3

2番目のケースでは、単語の拡張を防ぐためにアスタリスクがすぐ隣にあります-I(パターンに一致するファイルがないため-I*)。

$ seq 3 | xargs -I*  echo *
# Expands to:
$ seq 3 | xargs -I* echo main.py

*これには、テンプレートの(リテラルアスタリスク)インスタンスを入力に置き換えるにはxargsが必要です。echo main.pyテンプレートには*プレースホルダがまったく含まれていないため、main.py毎回印刷されます。

failglobBashで有効にする場合、またはzshでデフォルト設定を使用している場合、一致するものがないglobはエラーを生成し、コマンドは実行されません。)

コマンドが両方の発生を保護すると、*最初の試みと同じ出力が得られます。

$ seq 3 | xargs -I '*' echo '*'
1
2
3

ディレクトリに複数のファイルがある場合、引用符で囲まれていないファイルは*より明白な問題を引き起こす可能性があります。たとえば、2つのファイルがあり、次main.pyのような場合other.py

$ seq 3 | xargs -I *  echo *
# Expands to:
$ seq 3 | xargs -I main.py other.py echo main.py other.py

コマンドで実行を試みますxargs(現在の入力文字列に置き換えられます)。これにより、「コマンドが見つかりません」エラーが発生する可能性があります。または、ソート順の2番目のファイル名が次に実行可能なプログラムと一致する場合other.py echo main.py other.pymain.pyxargsPATHxargsそのプログラム、まさかecho


Bash拡張で何が起こっているのか、どの程度の可視性を得るのに役立つ方法はset -o xtrace。フラグを設定した後、次から始まる行の拡張が表示されます+

$ set -o xtrace
$ seq 3 | xargs -I * echo *
+ seq 3
+ xargs -I main.py echo main.py
1
2
3

$ seq 3 | xargs -I* echo *
+ seq 3
+ xargs '-I*' echo main.py
main.py
main.py
main.py

$ seq 3 | xargs -I '*' echo '*'
+ seq 3
+ xargs -I '*' echo '*'
1
2
3

関連情報