폴더에 대한 추적을 수행하려고 하는데 파일에 대해 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 대신 확장됩니다. 있는 그대로 )."foo
bar"
foo*.txt
find
단어분할이 매우 간단하기 때문입니다.오직실제로 공백으로 분할아니요실행 출력은 전체 쉘 구문을 통해 구문 분석됩니다. (그렇다면 명령 대체를 포함한 모든 확장이 항상 재귀적으로 실행된다는 의미이므로 매우 위험할 것입니다. 임의의 데이터를 상대적으로 안전하게 처리하기 위해 셸을 사용하는 것은 불가능합니다.)
파일의 한 섹션을 완전히 구문적으로 처리하려면 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
프로그래밍 방식으로 상용구를 생성하도록 할 수 있습니다.
또한보십시오:
- https://mywiki.wooledge.org/WordSplitting
- 변수에 저장된 명령을 어떻게 실행할 수 있나요?(관련 질문과 어레이 명령줄 구축에 대한 일반적인 예가 포함되어 있습니다)
- 인수에서 find 명령 작성
find
( 빌드 명령줄의 보다 구체적인 예가 포함되어 있습니다 )
답변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 \))