zsh globbing을 사용하여 경로 구성 요소를 선택적으로 지정하는 방법은 무엇입니까?

zsh globbing을 사용하여 경로 구성 요소를 선택적으로 지정하는 방법은 무엇입니까?

다음과 같은 디렉터리 구조가 있다고 가정해 보겠습니다.

% tree foo 
foo
├── bar
│   └── baz
└── baz

두 가지를 우아하게 매치하는 방법foo/bar/baz 그리고 foo/baz? 즉, bar/경로의 구성 요소를 선택적으로 만드는 방법은 무엇입니까 ?

foo/*/baz유효한 확장자가 아니기 foo/bar/baz때문에 일치합니다 . foo//baz선택적 그룹을 사용해 보았지만 다음과 같습니다.

% set -o KSH_GLOB
% echo foo/?(bar)/baz

또한 foo/bar/baz같은 이유로 ( foo//baz유효한 확장자가 아님) 로 확장됩니다. /에 따르면 그룹 내에 a를 포함하는 것은 일반적으로 불법이므로 zshexpn(1)예를 들어 foo/?(bar/)baz오류가 발생합니다.

특별히 이상한 경우는 아닌 것 같은데, 구글 검색이나 SE 검색에서는 관련 내용을 찾을 수 없습니다.

답변1

이것은 ksh 및 zsh glob의 문제점입니다. 중괄호를 사용할 수 있습니다.

echo foo{,/bar}/baz
echo foo{,/*}/baz    # you probably don't want this one, see below

그러나 교정기는 전체가 아니며, 교정기가 충분히 가까운지 여부는 수행 중인 작업에 따라 다릅니다.

주요 질문은 어떤 파일이 존재하는지, 일부 파일이 존재하지 않는 경우 어떻게 되기를 원하는지입니다. foo{,/bar}/baz두 단어로 확장되고 foo/baz파일 foo/bar/baz이 존재하는지 여부. 와일드카드를 사용하면 기본적으로 foo{,/*}/baz일치하는 파일이 없으면 오류가 발생합니다 . 존재 foo/*/baz하더라도 마찬가지입니다 . foo/baz다음 방법으로 이 문제를 해결할 수 있습니다.N 와일드카드 플래그:

echo foo{/*,}/baz(N)

그러면 일치하는 기존 파일 목록 foo/*/baz(목록이 비어 있더라도) 으로 확장되고 . 이는 작동하면 얻을 수 있는 것과 foo/baz동일합니다 . foo/(*/|)/baz(N)반면에 간단하게 동등한 것은 없습니다 foo/(*/|)/baz. 일치하는 항목이 없을 때 오류가 발생하려면 직접 수행해야 합니다.

bazes=(foo{,/*}/baz(N))
if (($#bazes == 0)); then echo >&2 "No bazes are belong to us"; return 1; fi

중괄호와 glob의 또 다른 차이점은 중괄호 내의 순서에 따라 확장 순서가 결정된다는 것입니다. 예를 들어 수정 시간에 관계없이 echo foo{,/*}/baz(Nom)항상 먼저 입력하세요 .foo/baz

답변2

실수로 >1개의 "선택적" 경로 이름 구성 요소를 일치시킨 경우에는 문제가 되지 않습니다. 다음을 수행할 수 있습니다.

% set -o EXTENDED_GLOB
% echo foo/(bar/)#baz

foo/bar이는 및 와 일치 foo/bar/baz하지만 foo/bar/bar/baz등과 도 일치합니다.

답변3

두 위치에서 일치하는 파일을 원하는지 명시적으로 말하지 않았습니다.오직, 또는모두그들은 나무에 있습니다. 모든 항목을 일치시킬 수 있는 옵션이 있는 경우 다음을 사용할 수 있습니다 **.

% mkdir -p foo/{bar,asdf/asdf,}/baz
% echo foo/**/baz       
foo/asdf/asdf/baz foo/bar/baz foo/baz

Bash에서도 작동합니다( globstar활성화됨).

$ shopt -s globstar
$ echo foo/**/baz       
foo/asdf/asdf/baz foo/bar/baz foo/baz

(zsh와 Bash 사이에는 몇 가지 주의 사항/차이점이 있습니다 **. 트리의 기호 링크입니다.)

관련 정보