私が理解している限り、アスタリスク文字は*
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 1
echo 2
echo 3
2番目のケースでは、単語の拡張を防ぐためにアスタリスクがすぐ隣にあります-I
(パターンに一致するファイルがないため-I*
)。
$ seq 3 | xargs -I* echo *
# Expands to:
$ seq 3 | xargs -I* echo main.py
*
これには、テンプレートの(リテラルアスタリスク)インスタンスを入力に置き換えるにはxargsが必要です。echo main.py
テンプレートには*
プレースホルダがまったく含まれていないため、main.py
毎回印刷されます。
(failglob
Bashで有効にする場合、または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.py
main.py
xargs
PATH
xargs
そのプログラム、まさか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