glob *.{a,b,}test와 함께 중괄호 확장을 사용할 때 zsh에서 "일치 없음"을 무시합니다.

glob *.{a,b,}test와 함께 중괄호 확장을 사용할 때 zsh에서 "일치 없음"을 무시합니다.

foldername확장자가 또는 이라는 test폴더 atest에 있는 모든 파일을 나열하고 싶습니다 btest.

내 즉시 생각은 실행하는 것이 었습니다ls ./foldername/*.{a,b,}test

확장명에 아무 것도 없는 경우가 아니면 잘 작동합니다 . atest이 경우 오류가 발생합니다 zsh: no matches found: ./foldername/*.atest.

이 오류를 무시하고 존재하는 파일을 인쇄할 수 있는 방법이 있습니까?

zsh와 Bash 모두에서 작동하려면 이것이 필요합니다.

답변1

~ 안에

ls -d ./foldername/*.{a,b,}test

{a,b,...}전역 연산자가 아닙니다. 이는 중괄호 확장이며 먼저 다음으로 확장됩니다.

ls -d ./foldername/*.atest ./foldername/*.btest ./foldername/*.test

그리고 각 glob은 개별적으로 확장되며, 일치하지 않는 glob이 있으면 명령이 예상대로 취소됩니다 zsh(또는 fish; 에서는 비슷한 동작을 얻으려면 옵션이 bash필요합니다 ).failglob

여기서는 모든 파일과 일치하는 단일 glob을 사용하고 해당 하나의 glob이 어떤 파일과도 일치하지 않는 경우에만 명령을 취소하려고 합니다.

ls -d ./foldername/*.(a|b|)test

을 사용하고 싶지 않습니다 nullglob. 일치하는 글로브가 없는 것처럼 ls인수 없이 실행되므로 현재 디렉터리를 나열하세요. cshnullglob일치하지 않는 glob을 제거하지만 모든 glob이 일치하지 않으면 여전히 명령을 취소하므로 점에서 더 좋습니다.

당신은 사용하고 싶지 않을 것입니다 nonomatch. 왜냐하면 그것은 당신에게 부끄러운 행동을 초래할 것이기 때문입니다 bash.

zsh및 모두에서 작동하는 glob 대안의 경우 bashksh glob( set -o kshglobin zshshopt -s extglobin bash)을 사용할 수 있습니다.

그런 다음 다음을 수행합니다.

ls -d ./foldername/*.@(a|b|)test

또는:

ls -d ./foldername/*.?([ab])test

일치하지 않을 때 glob이 문자 그대로 전달되는 것을 방지하려면 failglob옵션을 추가하세요 .bashls

보다nullglob이 기본값이 아닌 이유는 무엇입니까?자세한 내용은.

답변2

다음을 사용하여 이 작업을 수행하는 것이 가장 좋습니다 find.

find ./foldername -maxdepth 1 -name '*.atest' -o -name '*.btest' -o -name '*.test'

답변3

나는 이 문제에 직면했고 먼저 ls 자체를 해킹하여 해결했습니다. 작업을 마쳤을 때 필요한 것은 Trival C 프로그램뿐이라는 것을 깨달았습니다.

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

int main(int argc, char* argv[]) {
  struct stat statbuf;
  int i;
  for( i=1; i<argc; i++ ) {
    if( stat(argv[i],&statbuf) == 0 ) {
      printf("%s\n",argv[i]);
    }
  }
}

이 모든 작업과 필요한 작업은 명령줄 인수를 통해 실행하고 유효한 파일(즉, stat()이 성공하는 파일)에 해당하는 문자열을 에코하는 것입니다.

물론, 똑같이 간단한 Python, Perl 또는 stat를 실행하는 셸 함수를 사용하여 이를 에뮬레이트할 수 있지만 C로 작성하면 실행 속도가 훨씬 빨라집니다.

ls 해킹에 관해서는 내 개인 위키에 다음과 같은 내용을 올렸습니다.http://linux.chalisque.net/LsIgnoreMissing

답변4

@DopeGhoti의 댓글이 저에게 도움이 되었습니다.

즉, 다음과 같이 연산자를 /dev/null사용하여 오류를 리디렉션합니다 .2>

ls ./foldername/*.{a,b,}test 2> /dev/null

관련 정보