Bash에서 외부 명령에 대한 가변 길이 인수 행을 작성하는 올바른 방법

Bash에서 외부 명령에 대한 가변 길이 인수 행을 작성하는 올바른 방법

내 스크립트 입력에 따라 여러 다른 파일 세트를 찾으려면 Bash 함수에서 "find" 명령을 사용해야 합니다.

그래서 나는 다음과 같은 것을 가지고 있습니다 :

DAYS=30
case $1 in
A1) ARGLINE="-name 'FOO*.xml' -or -name 'BAR*.xml' -or -name 'BTT*.txt'"
    ;;
A2) ARGLINE="-name 'PO*xml' -or -name 'PR*xml'"
    ;;
...
esac
find . -maxdepth 1 -type f -mtime +${DAYS} `${ARGLINE}`

이것은 작동합니다.

그러나 다음과 같이 변수를 사용하여 일수를 검색하고 싶습니다.

DAYS=30
case $1 in
A1) ARGLINE="-name 'FOO*.xml' -or -name 'BAR*.xml' -or -name 'BTT*.txt'"
    ;;
A2) ARGLINE="-name 'PO*xml' -or -name 'PR*xml'"
    ;;
...
esac
if [[ $# -gt 1 ]]; then
    DAYS=$2
fi
find . -maxdepth 1 -type f -mtime +${DAYS} `${ARGLINE}`

이 기능이 실패하면찾다일치하는 파일을 찾을 수 없으며 다음 오류가 발생했습니다.

'-name' 명령을 찾을 수 없습니다. 'coreutils'(기본) 패키지의 'uname' 명령을 의미합니다. -name: 명령을 찾을 수 없습니다.

그러나 find가 일부 파일을 찾는 데 걸리는 일수가 이 값에 도달하면 제대로 작동합니다. 성공적인 실행의 출력을 다른 명령으로 파이프하려고 하면 실패합니다.

"찾기"에 대한 인수 줄을 어떻게 적절하게 구성해야 합니까?

답변1

에서는 bash배열을 사용합니다.

args=( '(' -name 'FOO*.xml' -or -name 'BAR*.xml' -or -name 'BTT*.txt' ')' )

)을 사용하므로 올바른 부울 논리 그룹을 생성하는 데 추가 괄호가 사용됩니다 -or.

find그런 다음 명령 에서 다음을 수행합니다 .

find ...some arguments... "${args[@]}"

사용하기 때문에 추가 문제가 있습니다.

`$ARGLINE`

$( $ARGLINE )이는 쉘이 $ARGLINE(해당 값)을 명령으로 실행하려고 시도하는 방법과 유사한 명령 대체입니다 . 이것이 "명령 '-name'을 찾을 수 없습니다"라는 메시지가 나타나는 이유입니다. 명령 대체는 실패하지만 find실행되므로 "작동한다"고 생각합니다.

답변2

여기서 가장 큰 문제는 따옴표가 따옴표 안에서 작동하지 않는다는 것입니다. 변수를 확장한 후 내부 따옴표는 다음과 같은 일반 문자일 뿐입니다.

$ foo='foo "bar doo"'
$ printf "<%s>\n" $foo
<foo>
<"bar>
<doo">

다음과 같은 명령 매개변수를 저장하려면 배열을 사용해야 합니다.

ARGS=(-name 'FOO*.xml' -or -name 'BAR*.xml' -or -name 'BTT*.txt')

쉘은 이 단계에서 따옴표를 처리하고 다른 쉘 단어를 다른 배열 요소로 저장합니다. 다음과 같은 배열을 사용하십시오.

find . "${ARGLINE[@]}"

원하거나 필요한 경우 배열을 하나씩 구성하여 동일한 배열을 생성할 수 있습니다.

ARGS=(-name 'FOO*.xml')
ARGS+=(-or -name 'BAR*.xml')
ARGS+=(-or -name 'BTT*.txt')

그러나 "인용"하기 위해 역따옴표도 사용한다는 점에 유의하세요 ${ARGLINE}. 그러면 명령 대체가 시작되고 ARGLINE콘텐츠가 명령으로 실행됩니다. 여기서 오류가 발생하고 쉘이 이라는 프로그램을 실행하려고 합니다 -name.


실제로, 귀하의 예에서는 그렇지 않습니다.필요매개변수에 공백이 없으므로 배열입니다. 여기서 가장 큰 문제는 일반적으로 공백 사이의 차이입니다.~ 사이매개변수 및 공백이내에명령줄을 문자열로 저장하면 매개변수가 손실됩니다. 그러나 귀하의 경우에는 이것이 효과가 있을 수 있지만 권장하지는 않습니다.

set -f       # disable globbing
ARGLINE="-name FOO*.xml -or -name BAR*.xml -or -name BTT*.txt"
find . $ARGLINE

관련 정보