ZSH — 특정 패턴을 무시하고 파일을 반복합니다(ls 또는 find 없음).

ZSH — 특정 패턴을 무시하고 파일을 반복합니다(ls 또는 find 없음).

'라는 제목의 기사를 방금 읽었습니다."ls의 출력을 구문 분석하면 안되는 이유". 디렉터리의 각 파일을 반복하고 싶은데 기사에서는 다음이 가장 기본적이고 이상적인 방법 중 하나라고 지적합니다.

for f in *; do
    echo $f
    # …do stuff
done

내가 이해하지 못하는 한 가지는 내가 어떻게 할 수 있느냐는 것입니다.특정 파일과 디렉터리를 무시하시겠습니까?저는 ZSH를 사용하고 있으며 켜져 있습니다 extendedglob. 그래서 나는 이것이 작동할 것이라고 생각했습니다: for f in *^.jpg; do…그러나 "*^.jpg"만 에코하고 파일은 없습니다.

루프를 본질적으로 동일하게 유지하면서 특정 패턴을 제외하는 기능을 어떻게 가질 수 있습니까? 보너스 질문: glob을 재귀적으로 만들 수 있나요?

답변1

Zsh는 파일을 열거하는 아주 좋은 방법을 제공합니다. 그들은 기록되어 있다설명서의 "파일 이름 생성"에서, 그러나 zsh 매뉴얼은 따라하기 쉽지 않습니다.

기본적으로 일치하는 파일이 없으면 오류가 발생합니다. 이는 일반적으로 명령줄에서는 바람직하지만 스크립트에서는 그렇지 않습니다. 이 오류를 비활성화하려면 스크립트 시작 부분에 오류를 배치하여 켜십시오.null_glob옵션:

setopt null_glob
for x in *; do …

또는 사용N 글로벌 예선:

# Reliably iterate over non-dot files
for x in *(N); do …

위의 코드 조각은 현재 디렉터리에 존재하지 않는 모든 파일을 반복합니다.파일 클릭. 그러한 파일이 없으면 루프는 전혀 실행되지 않습니다(sh와는 달리, 루프 본문은 풀린 glob에서 한 번 실행되고 *기본 zsh glob에서 오류가 발생합니다).

반복에 도트 파일을 포함하려면 다음을 엽니다.got_glob옵션또는 Dglob 한정자를 사용하세요.

# Reliably iterate over all files in the current directory
for x in *(DN); do …

더 장황하더라도 glob 한정자 방법을 사용하는 것이 좋습니다. 동일한 옵션이 설정되지 않은 스크립트에 해당 스니펫을 복사하여 붙여넣더라도 여전히 동일한 방식으로 동작하기 때문입니다.

이름을 기준으로 특정 파일을 제외하려면 다음을 사용할 수 있습니다.글로벌 운영자 ^그리고 ~. 이는 setopt extended_glob스크립트²에 있어야 합니다 (이는 .zshrc런타임 환경이나 1에서 상속되지 않습니다). 예를 들어, *.jpg파일을 제외하려면 *~*.jpg또는 ^*.jpg.

( *^.jpg당신이 작성한 내용은 기본적으로 zsh에서 오류를 발생시킵니다. 인쇄된 내용이 보이면 *^.jpgzsh를 실행 중이 아닌 것입니다 nomatch(기본적으로 켜져 있음). 이는 일반적으로 완료되었을 때 sh를 시뮬레이션할 때만 가능하거나 ksh를 시뮬레이션할 때만 가능합니다. 그렇지 않으면 실제로 sh 쉘에서 스크립트를 실행하고 있습니다. 아마도 누락되었기 때문일 것입니다.셰르본 라인상단에. )

setopt extended_glob
# Iterate over all the files in the current directory except *.jpg and .*
for x in *~*.jpg(N); do …

하위 디렉터리를 재귀적으로 탐색하려면 쉽습니다. 다음을 사용하세요.**/.

setopt extended_glob
# Iterate over all the files in the current directory and its (grand-)*children except *.jpg and .*
for x in **/*~*.jpg(N); do …

통과하다글로벌 예선, 이름 이외의 기준에 따라 파일을 선택할 수도 있습니다. 예를 들어 디렉터리, 심볼릭 링크 등을 제외하고 일반 파일만 반복하려면 다음을 수행하세요.

# Iterate over all regular files in the current directory and its (grand-)*children except *.jpg and .*
for x in **/*(.DN); do …

e임의의 코드를 실행하여 또는 glob 한정자를 사용하여 +파일을 포함 할지 여부를 결정할 수도 있습니다 . 그러나 for 루프에서 와일드카드 패턴을 사용하는 경우 필터링 코드를 루프 본문 상단에 배치하는 것이 더 명확합니다.

1 입력할 수 있지만 setopt extended_glob, 그 내용에 대해 가정하는 스크립트는 다른 컴퓨터나 다른 계정에서 충돌할 수 있으므로 ~/.zshenv사용하지 않는 것이 좋습니다.zshenv
. ²zsh 완료 기능을 작성하는 경우 이러한 기능은 extended_glob개방형 환경에서 실행됩니다.

관련 정보