내 디렉토리 구조는 다음과 같습니다.
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
해당 인수 하나를 토큰화하고 인용 제거하도록 셸에 지시할 수 있습니다. "${(Q@)${(Z[n])1}}"
( 는 ewline Z[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
.