동일한 문자열/패턴으로 끝나는 파일이 있는지 확인하는 데 문제가 있습니다. 파일 이름은 다음과 같을 수 있습니다.
abs_123.unl
xyz_123.unl
현재 내 코드는 다음과 같습니다. 단일 파일에서는 제대로 작동하지만 동일한 패턴의 파일이 여러 개 있으면 if 조건이 실패합니다.
if [ -s $AZWORK/*$PRCSID.unl ]
then
tar -cvzf $WORK/INET_$PRCSID.unl.gz $WORK/*$PRCSID.unl
fi
여기서 $PCSID는 파일의 마지막 세 자리를 나타냅니다.
이 쉘 스크립트를 여러 파일에서 작동하게 하려면 어떻게 해야 합니까?
답변1
파일의 "찾기" 및 "크기 조정"을 다음 사용자에게 위임합니다 find
.
find "$WORK" -maxdepth 1 -name "*$PRCSID.unl" -type f ! -size 0 -print0 | \
xargs -0 --no-run-if-empty tar -cvzf "$WORK/INET_$PRCSID.unl.gz"
"*_123.unl"
이렇게 하면 해당 패턴이 있을 수 있는 하위 디렉터리를 필터링할 수도 있습니다 .
옵션 find
:
-maxdepth 1
하위 디렉터리로의 재귀 방지-name "*$PRCSID.unl"
*
쉘 확장을 방지하기 위해 파일 이름을 인용하여 파일 이름과 일치시킵니다 .-type f
파일만! -size 0
크기가 중요합니다!-print0
NUL로 구분된 이름을 인쇄합니다. 여기서 꼭 필요한 것은 아니지만 파일 이름에 개행 문자가 포함되어 있어도 문제가 되지 않습니다.
옵션/매개변수 xargs
:
-0
stdin이 NUL로 구분되어 있다고 가정합니다(개행으로 구분되지 않음).--no-run-if-empty
표준 입력에 데이터가 없으면 실행되지 않습니다(즉, find에는 출력이 있습니다).- 나머지 줄은 실행할 명령으로 stdin의 데이터를 인수로 추가합니다.
답변2
간단히 이렇게 할 수 있습니다:
tar -cvzf "$WORK/INET_$PRCSID.unl.gz" "$WORK"/*"$PRCSID.unl"
답변3
패턴과 일치하는 파일이 있는지 확인하려면 다음과 같이 할 수 있습니다.
만약에 ["$(shopt -s nullglob; printf "%s" "$WORK"/*"$PRCSID".unl)" != ""] 그 다음에 tar -cvzf "$WORK/INET_$PRCSID.unl.gz" "$WORK"/*"$PRCSID".unl 필리핀 제도
.unl
( 한 위치에서 파일을 찾은 다음 다른 위치에서 보관할 계획은 없다고 가정합니다 .)
shopt -s nullglob
파일 이름 패턴이 일치하는 항목이 없으면 파일 이름 패턴이 아무 것도 "확장"되지 않으므로 작업 디렉터리에 이름이 it로 끝나는 파일이 없으면 123.unl
문자열 인수가 "$WORK"/*"$PRCSID".unl
사라지고 printf
인쇄할 항목이 남지 않습니다.
노트:
shopt -s nullglob
예를 들어 external 선언을 사용할 수 있습니다if
.shopt -s nullglob # 아마도 스크립트의 다른 곳에 있을 수도 있습니다. ⋮ if [ "$(printf "%s" "$WORK"/*"$PRCSID".unl)" != "" ] 그 다음에 tar -cvzf "$WORK/INET_$PRCSID.unl.gz" "$WORK"/*"$PRCSID".unl 필리핀 제도
스크립트를 실행하여 이 동작(일치하지 않는 패턴의 빈 확장)을 활성화하려는 경우.- 특별한 이유가 없는 한 항상 쉘 변수(예:
"$WORK"
and )를 인용해야 합니다."$PRCSID"
틀림없이당신은 당신이 무엇을하고 있는지 알고 있습니다. 변수를 참조하기만 하면 단편적으로 수행할 수 있습니다."$WORK"/*"$PRCSID".unl 및 "$WORK"/INET_"$PRCSID".unl.gz
또는 변수가 포함된 전체 단어를 인용할 수 있습니다. 예를 들면 다음과 같습니다."$WORK/"*"$PRCSID.unl" 및 "$WORK/INET_$PCSID.unl.gz"
"$WORK/*$PRCSID.unl"
그러나 이렇게 하면*
파일 이름 확장 패턴(예: 와일드카드 또는 glob)으로 작동하지 않도록 따옴표로 묶어서 이를 수행할 수 없습니다 . - 파일 이름 패턴은 제어할 수 있는 디렉터리 이름으로 시작하므로 특히 전체 경로( 로 시작
/
)인 경우 또는 최소한 보장할 수 있습니다.아니요첫 번째-
echo
) — 그렇다면 IE를 사용해 도 안전할 것입니다printf "%s"
.만약 ["$(shopt -s nullglob;에코"$WORK"/*"$PRCSID".unl)" != "" ] 그 다음에 tar -cvzf "$WORK/INET_$PRCSID.unl.gz" "$WORK"/*"$PRCSID".unl 필리핀 제도
물론 여기 성명서에서shopt -s nullglob
이 내용을 삭제할 수도 있습니다.if
또 다른 방법
만약 너라면필요if
예를 들어 상태/로그/오류 메시지를 작성하려면 - then
- else
(또는 적어도 if
- )를 가지려면 then
위의 방법을 사용해야 할 것입니다. 그러나 tar
파일이 있는 경우에만 명령을 실행하는 것이 유일한 관심사라면 생략 if
하고 then
수행 할 수 있습니다.
(shopt -s 결함 글로벌;tar -cvzf "$WORK/INET_$PRCSID.unl.gz" "$WORK"/*"$PRCSID".unl)
shopt -s failglob
즉, 어떤 것과도 일치하지 않는 파일 이름 패턴이 포함된 인수를 사용하여 명령을 실행하려고 하면
명령이 실행되지 않았습니다.. 위의 내용은 귀하의 질문에 있는 코드가 달성하려는 작업을 정확하게 수행합니다. tar
작업 디렉터리에 이름이 로 끝나는 파일이 있으면 명령을 실행 123.unl
하고 그렇지 않으면 실행하지 않습니다.
shopt -s failglob
마찬가지로 명령 과 명령을 분리할 수 있습니다 tar
.
shopt -s 결함 글로벌 # 아마도 스크립트의 다른 곳에 있을 수도 있습니다. ⋮ tar -cvzf "$WORK/INET_$PRCSID.unl.gz" "$WORK"/*"$PRCSID".unl스크립트를 실행하여 해당 동작을 달성하려는 경우(일치하지 않는 패턴으로 명령을 실행하지 않음)
답변4
find
명령은 필요한 파일을 찾은 다음 다음과 같은 결과에 대해 명령을 실행할 수 있습니다.
find $WORK -name *.unl -exec tar -zcvf $WORK/INET_$PRCSID.unl.gz {} \;