私のディレクトリ構造は次のとおりです。
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]
、引数拡張フラグを使用して、Q
1つの引数をトークン化して引用符を削除するようにシェルに指示することもできます。"${(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
--opt3
cargo
ただし、ユーザーがすべてのパラメータをスクリプトに個別に渡すことができる場合(構文は次のとおりです)。彼ら上記の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
。