저는 Travis-CI에서 Find를 사용하여 프로그래밍 방식으로 특정 파일 형식을 확인하고 있습니다. (정확히 말하면 쉘체크 체크입니다.)
그러나 find
그에 의해 실행된 명령/서브쉘의 종료 코드를 사용하는 경우에는 "메인 스크립트"로 전달되지 않으므로 자연스럽게 폐기됩니다.
예를 들어 다음은 find 명령입니다.
find . -type f -iname "*.sh" -exec sh ./testScripts.sh "{}" \;
./testScripts.sh
테스트 결과에 따라 0 또는 >= 1로 종료될 수 있습니다.
올바른 종료 코드로 올바르게 종료되지만 testScripts.sh
명령 find
의 종료 코드는 항상 "0"입니다. 내가 원하는 건 만약에파일/실행오류, 이 오류는 Travis-CI에 "전파"되었습니다.
어떻게 해야 하나요?
답변1
의견에서 Stephen Kitt의 제안을 사용하십시오.
find . -type f -iname "*.sh" -exec sh -c 'for n; do ./testScripts.sh "$n" || exit 1; done' sh {} +
이렇게 하면 sh -c
스크립트가 0이 아닌 종료 상태로 가능한 한 빨리 종료됩니다 testScript.sh
. 즉, find
0이 아닌 종료 상태로도 종료됩니다.
더하기 기호로 끝나는 경우 기본 경로 이름을 평가하는 경로 이름은 세트로 집계되고 유틸리티는 와 유사하게 세트당 한 번씩 호출됩니다
xargs(1)
. 0이 아닌 종료 상태로 통화가 종료되면 이 작업find
도 결국 수행됩니다., 그러나 이로 인해find
조기 종료되지는 않습니다.
댓글의 질문에 관해서 :
for n; do ... ; done
이상해 보이지만 반복할 수 있는 항목이 없고for
루프가 암시적으로 반복된다는 점을 깨닫는다면 이해가 됩니다"$@"
.sh
끝에 있는 꼬리는$0
껍질 에 배치됩니다sh -c
.{}
많은 경로 이름으로 대체됩니다 . 거기 에 없으면sh
첫 번째 경로 이름은 종료되고$0
거기에 없기 때문에 루프에서 선택되지 않습니다$@
.$0
일반적으로 현재 인터프리터의 이름이 포함됩니다(쉘에서 생성된 오류 메시지에 사용됩니다sh -c
).
답변2
xargs
xargs
명령이 실패하면 1에서 125(GNU의 경우 123) 사이의 종료 상태로 종료되고, 명령이 실패하고 상태 255로 종료되면 중단됩니다.
(with)의 출력을 안정적으로 사용 xargs
하고 명령의 표준 입력을 유지하려면 GNU가 필요합니다. 따라서 GNU와 프로세스 교체를 지원하는 셸을 사용하십시오. 예를 들어 다음과 같습니다.find
-print0
xargs
xargs
ksh
zsh
bash
xargs -n1 -r0a <(find . -type f -iname '*.sh' -print0) sh ./testScripts.sh
또는 첫 번째 실패 시 중단합니다.
xargs -r0a <(find . -type f -iname '*.sh' -print0) sh -c '
for file do
sh ./testScripts.sh "$file" || exit 255
done' sh
find
(POSIX 코드)를 사용하여 첫 번째 오류 발생 시 중단 할 수도 있습니다 .
find . -type f -name '*.[sS][hH]' -exec sh -c '
for file do
if ! sh ./testScripts.sh "$file"; then
kill -s PIPE "$PPID"
exit 1
fi
done' sh {} +
(SIGPIPE를 더 적게 사용하십시오.시끄러운신호를 내보내려면 일부 셸을 사용하세요(예 bash
: ). 이로 인해 find
종료되고 0이 아닌 종료 상태로 반환됩니다.
실패한 명령(여기서는 마지막)의 종료 상태에 대한 정확한 값을 얻으려면 zsh
또는 를 사용하고 bash
다음을 수행할 수도 있습니다.
ret=0
while IFS= read -rd '' -u3 file; do
sh ./testScripts.sh "$file" 3<&- || ret=$?
done 3< <(find . -type f -iname '*.sh' -print0)
다음을 사용하더라도 이 작업을 수행할 zsh
필요조차 없습니다 find
.
set -o extendedglob
ret=0
for file (./**/*(#i).sh(D.)) {
./testScripts.sh $file || ret=$?
}