다중 부분 인수에 대한 Bash globbing

다중 부분 인수에 대한 Bash globbing

find다음은 제가 실행하려는 명령의 몇 가지 예 입니다 . 저는 와일드카드를 사용하여 (예를 들어) 조건자가 함께 연결된 find 명령을 생성할 수 있는 다양한 방법을 찾고 있습니다.

find각 항목 앞에 -name이 필요하고 각 항목 사이에 -o가 필요하기 때문에 작동하지 않습니다 .

find . -name \*.{sh,pl,sql}
#find . -name *.sh *.pl *.sql

후행으로 인해 작동하지 않습니다 -o. 실패할 수밖에 없는 주장을 하는 것이 가능하지만 이상적이지는 않습니다. 또한 내 바로 가기가 이제 내 출력보다 길어졌습니다.

find . `for X in {sh,pl,sql}; do echo -name \\\*.$X -o ;done`
#find . -name \*.sh -o -name \*.pl -o -name \*.sql -o

하나의 매개변수( )로 그룹화되어 있기 때문에 실패합니다 find: unknown predicate '-name *.sh'. 또한 -o와의 연결 부족이 여전히 나타납니다.

find . -name\ \*.{sh,pl,sql}

작동하지만 와일드카드가 포함되지 않습니다(답변: 답변이 아님).

find .  -regex '.*\(sh\|pl\|sql\)'    

답변1

IMHO, 이 -false아이디어가 핵심입니다. 다음을 추가하겠습니다.

find . -false $(echo "-o -name *."{sh,pl,sql})

간단히 everything 을 인용하여 bash가 전체 패턴을 반복하도록 할 수 있으며 -o -name, 그런 다음 하위 쉘에서 이를 반환하여 인용으로 만들어진 그룹을 "해제"할 수 있습니다. 이 접근 방식의 문제점은 패턴의 따옴표가 작동하지 않는다는 것입니다.


편집: 이 솔루션의 또 다른 함정에 대해서는 Michał Šrajer의 의견을 참조하십시오. 별표 앞에 백슬래시를 넣을 수는 없습니다. 명령 대체는 *확장될 a 를 반환하거나 \*있는 그대로 find(!)에 전달될 a 를 반환합니다. 적어도 그것이 내 로컬 bash가 작동하는 방식입니다.

이것이 내가 할 수 있는 최선이다:

 (GLOBIGNORE='*:.*'; find . \( -false $(echo "-o -name *."{sh,pl,sql,xml}) \) -print)

행운을 빌어요:)

그런데 만약 당신이 그렇다면아니요더 많은 매개변수를 추가하려면 find물론 를 사용하세요 xargs. 이 경우에는 따옴표와 모든 항목이 완벽하게 작동합니다.

echo "-o -name *."{sh,pl,sql} | xargs find . -false

답변2

find사용되지 않습니다 glob(). 사용됩니다 fnmatch(). 그렇기 때문에 -name조건자에서 사용할 수 있는 유일한 메타 문자는 *, ?및 입니다.[]

후행 문제를 해결하려면 -o다음을 입력하는 것이 좋습니다.괄호그리고추가하다-false술부:

( -name AAA -o -name BBB -o -name CCC -o -false )

답변3

나는 이것이 여기에 있는 예라고 가정하고 있으며, find패턴을 단일 매개변수로 결합할 수 있는 솔루션(예: 두 가지 가능한 접근 방식이 있습니다. 문자열을 만들고 쉘이 문자열을 여러 인수로 분할하도록 하거나(공백이 있는 한) 배열을 만들 수 있습니다.find-regex

명령 대체와 함께 문자열 작성 방법을 사용하는 것은 시도보다 훨씬 쉽지 않습니다.

find . $(for X in sh pl sql; do echo "-name \\*.$X" -o; done | sed 's/-o *$//')

명령 전에 루프에 문자열을 작성할 수도 있습니다 find. 이렇게 하면 스크립트가 더 명확해질 것입니다.

find_options=
for x in sh pl sql; do
  find_options="$find_options -o -name \\*.$x"
done
find_options=${find_options# -o}
find . $find_options

쉘이 배열(예: bash, ksh 또는 zsh)을 지원하는 경우 추가 따옴표를 삽입할 필요가 없도록 해당 배열을 사용하는 것이 좋습니다.

find_options=()
for x in sh pl sql; do
  find_options+=(-o -name "*.$x")
done
unset "find_options[0]"
find . "${find_options[@]}"

1 명령줄에서는 이식성에 대해 걱정할 필요가 없으며 사용자 입력에 대해 걱정할 필요가 없기 때문에 필요한 만큼만 인용할 수 있습니다. 복사-붙여넣기로 중복을 처리할 수 있습니다.

관련 정보