파일의 여러 이름 필터를 사용하여 bash 스크립트에서 find 명령을 실행할 수 있습니까?

파일의 여러 이름 필터를 사용하여 bash 스크립트에서 find 명령을 실행할 수 있습니까?

폴더에 대한 추적을 수행하려고 하는데 파일에 대해 find -name 필터를 사용하고 싶습니다. 그래서 필터가 포함된 filter_files라는 파일을 준비했습니다. 예를 들면 다음과 같습니다.

cat filter_files:
-name "a.txt" -o -name "b.txt"

find 명령을 실행하고 위의 필터를 추가해 보았지만 아무 것도 반환하지 않습니다. 파일 내용을 작성하여 find 명령에 붙여넣으면 성공합니다.

내 bash 파일의 관련 줄은 다음과 같습니다.

local filter=$(cat $filter_files)
find_files=$(find "$path" -type f \( $filter \) )

내가 원하는 것을 할 수 있는지 설명해 주시겠어요? 그렇다면 어떻게 작동하게 할 수 있습니까?

답변1

파일에 다음이 포함된 경우

-name "a.txt" -o -name "b.txt"

당신은 달리다

find "$path" -type f \( $(cat file) \) 

그런 다음 쉘은 cat단어 분할을 통해 출력을 실행하여 매개변수 -name, "a.txt", -o, -name및 따옴표를 생성합니다 "b.txt". 여기서 따옴표는 실제로 매개변수의 일부입니다. (따옴표도 공백을 보호하지 않습니다. 이와 같은 입력 문자열은 두 개의 필드 와 를 "foo bar"생성합니다 . 또한 분할 결과는 파일 이름/와일드카드로 생성되므로 이 시점에서는 Pass 대신 확장됩니다. 있는 그대로 )."foobar"foo*.txtfind

단어분할이 매우 간단하기 때문입니다.오직실제로 공백으로 분할아니요실행 출력은 전체 쉘 구문을 통해 구문 분석됩니다. (그렇다면 명령 대체를 포함한 모든 확장이 항상 재귀적으로 실행된다는 의미이므로 매우 위험할 것입니다. 임의의 데이터를 상대적으로 안전하게 처리하기 위해 셸을 사용하는 것은 불가능합니다.)

파일의 한 섹션을 완전히 구문적으로 처리하려면 run 명령을 사용해야 합니다 eval. 예를 들면 다음과 같습니다.

eval 'find "$path" -type f \( '"$(cat file)"' \)'

여기에서 셸이 따옴표 및 명령 대체를 처리한 후 eval다음 문자열을 얻습니다. 이 문자열은 따옴표 처리 및 모든 확장을 포함하여 셸 명령으로 처리됩니다.

find "$path" -type f \( -name "a.txt" -o -name "b.txt" \)

(참고로 파일에 eg 가 포함되어 있으면 명령이 실행됩니다. 다만 이중 처리되지 않도록 내부 쉘 확장 "$(reboot)"에 맡깁니다 .)"$path"

예를 들어 파일의 단어를 배열에 할당한 eval다음 최종 명령에서 해당 배열을 사용하는 등 여러 단계로 위의 작업을 수행할 수 있습니다. 아이디어와 고려 사항은 동일합니다.


파일 형식을 다시 고려해 볼 수도 있습니다. 예를 들어 각 인수를 별도의 줄에 배치하고 인용을 해제하면 구문 분석이 더 쉬워집니다.

예를 들어, 파일이 다음과 같은 경우:

-name
a.txt
-o
-name
foo bar.txt

readarray각 입력 줄을 별도의 배열 요소로 읽어 비슷한 작업을 수행할 수 있습니다 .

#!/bin/bash
readarray -t args < file 
find "$path" -type f \( "${args[@]}" \)

(개행 문자가 있는 파일 이름을 처리할 수 없다는 점에서 여전히 제한적이지만 이러한 경우는 아마도 드물고 다른 문제를 일으킬 수 있습니다.)

그런 다음 필요한 것이 -name일치하는 것뿐이라면 파일에 패턴을 나열하고 -o -name프로그래밍 방식으로 상용구를 생성하도록 할 수 있습니다.

또한보십시오:

답변2

사용:

-o쉽게 만들려면 줄을 분리하고 파일에서 제거 해야 합니다 .

find "$path" -type f $(sed '1q;d' filter_files) -o $(sed '2q;d' filter_files)

또는:

단일 문자열.

filter_conditions=$(<sed '1q;d' filter_files)
find_files=$(find "$path" -type f \( $filter_conditions \))

관련 정보