사용자 변수를 사용하여 찾기

사용자 변수를 사용하여 찾기

몇 가지 변수를 사용하여 find를 호출하려고 합니다. 지금까지 나는 이것을 가지고 있습니다 :

DIRECTORY="./ "
FILENAME=-regex" .*test.*"
find $DIRECTORY $FILENAME

좋은 결과. 파일 이름을 다음과 같이 변경하면:

FILENAME=-regex" .*"

디렉토리의 모든 파일을 나열하려면 다음 오류가 발생합니다.

find: paths must precede expression: ..

내가 뭘 잘못했나요?

답변1

변수의 내용 FILENAME

-regex .*test.*

따옴표는 변수 값의 일부가 아니라 셸 구문의 일부입니다. 쉘은 이것이 할당임을 발견하기 전에도 행을 구문 분석하고 따옴표를 해석합니다.

line을 실행하면 find $DIRECTORY $FILENAME먼저 $FILENAME해당 값으로 대체됩니다. 그런 다음 쉘은 변수 값에 대해 두 단계의 확장을 수행합니다. 즉, 변수에 공백이 포함된 별도의 단어(원하는 경우)로 분할하고 각 단어에 대해 와일드카드(즉, 와일드카드 확장)를 수행하여 다음과 같이 .*확장됩니다. 현재 디렉터리에 있는 파일 점으로 시작하는 파일 이름 목록입니다.

.*test.*패턴이 어떤 파일과도 일치하지 않아 패턴 자체로 확장되므로 첫 번째 코드 조각에는 문제가 없습니다 .

여러 단어를 저장해야 하는 경우 안정적인 솔루션은 문자열 변수 대신 배열 변수를 사용하는 것입니다.

DIRECTORY="./"
EXPRESSION=("-regex" ".*test.*")
find "$DIRECTORY" "${EXPRESSION[@]}"

또는 여러 디렉터리를 허용하려는 경우:

DIRECTORIES=("./")
EXPRESSION=("-regex" ".*test.*")
find "${DIRECTORIES[@]}" "${EXPRESSION[@]}"

"${EXPRESSION[@]}"배열의 요소 목록으로 확장됩니다(별도의 단어로 표시됨).

"$foo""$(foo)"값의 토큰화 및 와일드카드 지정을 원하지 않는 한 변수 대체 및 명령 대체 주위에는 항상 큰따옴표를 사용해야 합니다 .

여기서는 bash를 사용하고 있으므로 배열이 올바른 솔루션입니다. 배열이 없는 셸에는 여러 가지 가능성이 있습니다. 실제로 배열 변수인 위치 매개변수를 사용할 수 있지만 이는 다른 목적으로 사용하지 않는 경우에만 가능합니다.

set -- "./"                  # start with the directory
set -- "$@" -regex '.*'      # add the expression
find "$@"                    # go

또 다른 접근 방식은 나중에 토큰화 및 와일드카드를 준비하기 위해 변수의 내용을 적절하게 인용하는 것입니다. ?*[와일드카드 문자( ) 앞에 백슬래시를 사용하여 문자 그대로 해석되도록 할 수 있습니다 .

DIRECTORY=./
EXPRESSION='-regex .\*'
find "$DIRECTORY" $EXPRESSION

또 다른 접근 방식은 와일드카드를 비활성화하는 것입니다 set -f. 이 find줄을 실행하기 전에. set +f나중에 필요할 경우 반드시 다시 켜십시오. 토큰화를 사용하므로 조건자 인수의 일부로 공백 문자를 전달할 수 없습니다 find.

DIRECTORY=./
EXPRESSION='-regex .*'
set -f
find "$DIRECTORY" $EXPRESSION

또한 명령을 변수에 넣으려고 하는데 복잡한 경우가 항상 실패합니다! bash FAQ에서.

답변2

누구나

directory=.
match=(-regex '.*test.*')
find "$directory" "${match[@]}"

또는 (여기서 ","를 사용하여 강조):

directory=.
match='-regex,.*test.*'
IFS=,
set -f
find "$directory" $match

또는:

directory=.
match="-regex '.*test.*'"
eval 'find "$directory" '"$match"

답변3

변수에 대한 참조가 없습니다. 그러므로 쉘이 보는 것은

find ./  -regex .*

그리고 그것은 .*.. ..

관련 정보