ユーザーが指定したパラメータを使用して、サブディレクトリで貨物コマンドを実行します。

ユーザーが指定したパラメータを使用して、サブディレクトリで貨物コマンドを実行します。

私のディレクトリ構造は次のとおりです。

rust/
├── dir1/
│   └── Cargo.toml
└── dir2/
    └── Cargo.toml

rustこのディレクトリで実行するzshスクリプトを生成し、ファイルを含むCargo.toml各サブディレクトリに対してcargoユーザーが指定したパラメータを使用してコマンドを実行したいと思います。

例:

run.sh "test -- --ignored"実行するcargo -v test -- --ignored --manifest-path ./dir1/Cargo.toml必要がありますcargo -v test -- --ignored --manifest-path ./dir2/Cargo.toml

二重引用符は、シェルが混乱するのを防ぐのに役立ちます--。ユーザーは二重引用符なしで他のパラメータを渡すことができます--

これを試しましたが、find . -name 'Cargo.toml' -type f -print -exec cargo -v "$@" --manifest-path {} \;「エラー:対応するサブコマンドなし:test --ignored」エラーが発生しました。明らかに、内容全体は個々の文字列ではなく文字列として渡されます。

どうすればいいですか?

答え1

シェルはそうではありません混乱させる--

ただし:

#! /bin/zsh -
for toml (**/Cargo.toml(N.)) cargo -v "$@" --manifest-path $toml

そしてそれを呼び出す:

that-script test -- --ignored

zsh globbingを使用すると、次のようないくつかの利点がありますfind

  • 隠しファイルとディレクトリは無視されます(D必要でない場合は修飾子を追加してください)。
  • リストがソートされました。
  • {}含まれているパラメータをに渡すことができますcargo

スクリプトに引数を渡し、シェルがそれを空白文字に分割し、結果の単語を別の引数として渡すようにするには、cargo次のようにします。

#! /bin/zsh -
for toml (**/Cargo.toml(N.)) cargo -v ${(s[ ])1} --manifest-path $toml

$1または文字ごとに分割します(デフォルトは空白、タブ改行、およびnul)。$IFS$=1

その後、次のように電話できます。

that-script 'test -- --ignored'

ただし、これは、ユーザーがスペース(またはIFS文字)を含むパラメーターをに渡すことができないことを意味しますcargo

zあるいはZ[options]、引数拡張フラグを使用して、Q1つの引数をトークン化して引用符を削除するようにシェルに指示することもできます。"${(Q@)${(Z[n])1}}"( は ewlineZ[n]n区切り文字としても許可されます。 コメントのz[Cn]識別と削除、二重引用符内の空の要素の保持を参照)最初に戻ることができます。C@$argv$@

#! /bin/zsh -
argv=( "${(Q@)${(Z[n])1}}" )
for toml (**/Cargo.toml(N.)) cargo -v "$@" --manifest-path $toml

その後、次のことができます。

that-script "test -- --opt1='foo bar' --opt2=$'blah\nblah' --opt3 ''"

たとえば、and 、、testおよび空の文字列は別々の引数として渡されます。----opt1=foo bar--opt2=blah<newline>blah--opt3cargo

ただし、ユーザーがすべてのパラメータをスクリプトに個別に渡すことができる場合(構文は次のとおりです)。彼ら上記のZ/フラグQには引用構文が必要ですが、上記zshの最初の例のように標準と一緒に渡すスクリプトが必要です。cargo"$@"


--manifest-path path/to/Cargo.tomlこれで、問題はサブコマンドのオプション区切り文字の前にあることがわかりました。次のように、これらのパラメータをいつでもユーザー転送パラメータのリストに挿入できます。--test

#! /bin/zsh -
for toml (**/Cargo.toml(N.)) (
  argv[2,0]=(--manifest-path $toml)
  cargo -v "$@"
)

これにより、ユーザーが呼び出すとスクリプトがthat-script test -- --ignored最終的に呼び出されますcargo -v test --manifest-path path/to/Cargo.toml -- --ignored

関連情報