내 스크립트 입력에 따라 여러 다른 파일 세트를 찾으려면 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