선택적 대괄호 인수를 사용하여 찾기

선택적 대괄호 인수를 사용하여 찾기

조회에 선택적 그룹화 매개변수 목록을 추가하는 방법은 무엇입니까?

예를 들어 기본 매개변수 배열을 사용하여 지정된 다른 변수 조건에 관계없이 항상 검색되는 파일을 정의합니다.

# args to find any files ending _count or _scan

._. fargs=( -type f -name '*_count' -o -name '*_scan' )
._. cd /sys/fs/ext4/sda1
._. find . \( "${fargs[@]}" \) 2> /dev/null
./mb_min_to_scan
./errors_count
./mb_max_to_scan
./msg_count
./warning_count

선택적 추가 매개변수 추가

._. fpterm=warning
._. fpterm2=max
._. fANDargs=( -ipath "*$fpterm*" -o -ipath "*$fpterm2*" )

(a 또는 b 또는 c) 및 (d 또는 e 또는 f) 형식으로 찾기를 수행하려면 괄호 안의 선택적 매개변수를 사용하십시오.

._. find . \( "${fargs[@]}" \) \( "${fANDargs[@]}" \) 2> /dev/null
./dm-1/mb_max_to_scan
./dm-1/warning_count
./dm-0/mb_max_to_scan
./dm-0/warning_count
./sda1/mb_max_to_scan
./sda1/warning_count

그러나 선택적 arg 배열이 비어 있으면 다른 조건 충족이 중지되고 파일을 전혀 찾지 못합니다.

._. fANDargs=()
._. find . \( "${fargs[@]}" \) \( "${fANDargs[@]}" \) 2> /dev/null
._. 

빈 괄호는 문제를 일으킬 수 있습니다.

._. find . \( "${fargs[@]}" \) \( \) 2> /dev/null
._.

그러나 일반적으로 빈 arg 배열은 다른 조건이 충족되는 것을 방해하지 않습니다.

._. fANDargs=()   
._. echo "${fANDargs[@]}"

._. find . \( "${fargs[@]}" \) "${fANDargs[@]}" 2> /dev/null
...
./sda1/mb_min_to_scan
./sda1/errors_count
./sda1/mb_max_to_scan
./sda1/msg_count
./sda1/warning_count

따라서 선택적 args 배열이 비어 있지 않은 경우에만 괄호를 추가할 수 있다면 이 명령이 작동할 수 있습니다.

하지만 조건부로 괄호를 추가하는 방법은 무엇입니까?

다음과 같이 배열에 괄호를 추가하면 작동하지 않는 것 같습니다.

._. fpterm=warning
._. fANDargs=()
._. [ ! -z $fpterm ] && fANDargs+=( '\(' -ipath "*$fpterm*" '\)' )
._. echo "${fANDargs[@]}"
\( -ipath *warning* \)
._. find . \( "${fargs[@]}" \) "${fANDargs[@]}" 2> /dev/null
._.

답변1

[ ! -z $fpterm ] && fANDargs+=( '\(' -ipath "*$fpterm*" '\)' )

여기에 큰따옴표가 있습니다. 레이어 하나만 사용해 보세요.

fANDargs+=( \(  -ipath "*$fpterm*" \)  )   # or  
fANDargs+=( '(' -ipath "*$fpterm*" ')' )   # or with "(" and ")"

(또한 따옴표를 사용해야 합니다 [ ! -z "$fpterm" ])

일반적으로 명령에서 직접 단어를 사용하는 것과 똑같은 방식으로 배열 할당에 단어를 사용합니다. "${array[@]}"당신처럼 따옴표를 사용하면 배열의 내용이 확장됩니다.추가 수정이 필요하지 않습니다..

(이것은 사람들이 종종 잘못 이해하는 부분입니다. 그들은 쉘이 확장 결과에 대한 따옴표를 처리할 것으로 기대하는 것 같습니다. 그렇지 않습니다. 여기서는 "일반적인" 프로그래밍 언어에 더 가깝습니다. 따옴표를 사용하여 제거하십시오. 분할+글로브의 문제.)

물론 여기서의 맥락은 find그 자체로 보고 싶은 것은 대괄호를 있는 그대로(다른 인수로) 있다는 것입니다. 따옴표를 볼 필요는 없지만 볼 필요는 있습니다.껍데기괄호는 쉘 구문의 일부인 특수 문자이기 때문에 필요합니다. 따라서 따옴표 없이 사용할 수 있지만 somecmd { foo bar }에서 사용해야 합니다 somecmd \( foo bar \).


그런데 GNU find는 빈 괄호 세트에 대해 경고합니다.

$ find . \( \)
find: invalid expression; empty parentheses are not allowed.

그리고 논리적으로 말하면 어쨌든 이상해 보입니다. 내 첫 번째 본능은 빈 대괄호가 false로 평가되어야 하며, 이로 인해 find \( whatever \) \( \)항상 불일치가 발생한다는 것입니다. 그러나 이는 Busybox가 수행하는 것처럼 true로 해석될 수도 busybox find . \( \) -name '*.txt'있으며 busybox find . -name '*.txt'.

관련 정보