Bash에 여러 패턴이 있는지 확인하는 방법

Bash에 여러 패턴이 있는지 확인하는 방법

** 와일드카드를 포함하는 여러 패턴이 있으므로 다음과 같이 설정합니다.

foo/**/bar.xml
foo/**/baz.xml

샘플 디렉터리 트리가 있습니다.

$ tree foo/
foo/
└── deep
    ├── baz.xml
    └── even
        └── deeper
            └── baz.xml

이러한 패턴이 충족되는지 확인하는 가장 간단한 방법은 무엇입니까? 정확하게 말하자면: 0이 아닌 값을 반환합니다.없는 경우에만찾을 수 있습니다. 지금까지 제가 생각한 것은 globstarand 를 사용하는 것입니다 nullglob. 그러나 ls이는 여기서는 옵션이 아니며 마치 패턴이 충족되지 않는 것처럼 현재 디렉터리를 나열합니다. 그래서 echo다음과 같이 활용해야 합니다 .

$ (shopt -s globstar nullglob; echo foo/**/bar.xml foo/**/baz.xml) | grep .
foo/deep/baz.xml foo/deep/even/deeper/baz.xml
$ echo $?
0

그리고

$ (shopt -s globstar nullglob; echo foo/**/bar.xml foo/**/beque.xml) | grep .
$ echo $?
1

그렇습니다. 작동합니다. 하지만 어쩌면 내가 뭔가를 놓치고 있을지도 몰라더 단순하고/더 우아하다이 목표를 달성하는 방법은 무엇입니까?

답변1

다음 기능을 사용할 수 있습니다.

non_empty() (($#))
has() (
  IFS=
  set +o noglob
  shopt -s globstar nullglob extglob
  shopt -u failglob # which has precedence over nullglob!
  for glob do
    non_empty $glob && return
  done
  false
)
if has 'foo/**/bar.xml' 'foo/**/baz.xml'; then
  echo matches found
fi

(또는 has 'foo/**/ba[rz].xml'또는 (와 함께 extglob) has 'foo/**/@(bar|baz).xml'또는 has 'foo/**/bar.xml' || has 'foo/**/baz.xml')

첫 번째 일치하는 글로브에서 중지됩니다.

보다 효율적으로 만들고 첫 번째 일치에서 중지하려면 zsh반대와 해당 Y1glob 한정자를 사용할 수 있습니다.

has() {
  local glob
  for glob do
    ()(($#)) $~glob(NY1) && return
  done
  false
}

non_empty( 익명 함수에도 인라인됩니다 .)

**/재귀적 기능은 90년대 초반 zsh에서 제공되었으며 기본적으로 활성화되었습니다(bash에 의해 복사되었지만 2000년대 후반에는 기본적으로 활성화되지 않았습니다). 교체는 has 'foo/**/(bar|baz).xml'in 으로 수행 됩니다 zsh.

에서는 zsh다음 작업도 수행할 수 있습니다.

alias has='noglob has'

할 수 있는 것:

if has foo/**/bar.xml foo/**/baz.xml; then
  echo matches found
fi

글로벌 운영자를 인용할 필요가 없습니다.

답변2

위치 인수 목록을 재정의할 수 있는 경우:

shopt -s globstar nullglob

set -- foo/**/bar.xml foo/**/baz.xml

if [ "$#" -ne 0 ]; then
    echo matches found
fi

이는 위치 매개변수 목록을 와일드카드 패턴과 일치하는 이름으로 설정합니다. 유효 하므로 nullglob일치하는 항목이 없으면 목록은 비어 있습니다. 값은 $#위치 인수 목록의 길이입니다.

서브셸에서 실행한다는 아이디어를 활용하세요.

( shopt -s globstar nullglob; set -- foo/**/bar.xml foo/**/baz.xml; [ "$#" -ne 0 ] )

위치 인수 목록 대신 배열을 사용하십시오.

shopt -s globstar nullglob

names=( foo/**/bar.xml foo/**/baz.xml )

if [ "${#names[@]}" -ne 0 ]; then
    echo matches found
fi

관련 정보