"file" 명령의 출력을 구문 분석하여 "find"로 생성된 파일을 필터링합니다.

"file" 명령의 출력을 구문 분석하여 "find"로 생성된 파일을 필터링합니다.

node_modules저는 node.js 폴더의 내용이나 Python의 virtualenv기본 종속성을 검사하는 빠른 도구를 작성 중입니다. 이에 대한 빠른 첫 번째 근사치로 다음 명령을 작성했습니다.

find . | xargs file | awk '/C source/ {print $1} /ELF/ {print $1}'

거짓 긍정은 허용하지만 거짓 부정은 허용하지 않습니다(예: 파일에 문자 그대로 문자열이 포함되어 있거나 ELF의심 스러운 것으로 표시될 수 있음). 그러나 이 스크립트는 긴 파일 이름( 분할되므로)과 공백이 포함된 파일 C source에서도 실패할 수 있습니다 . xargs공백으로 분할됨) 및 줄바꿈이 포함된 파일 이름(find가 경로를 구분하기 위해 줄바꿈을 사용하기 때문).

find출력 file {}(아마도 출력에서 ​​경로를 완전히 제거하기 위해 몇 가지 추가 옵션을 사용 file)이 특정 정규식과 일치하는지 확인하여 생성된 경로를 필터링하는 방법이 있습니까?

답변1

깨달음을 달성하는 핵심 요소는 find다음과 같습니다.

find업무는 파일을 찾는 것이 아니라 표현식을 평가하는 것입니다. 예, find물론 파일을 찾을 수 있지만 실제로는 부작용일 뿐입니다.

--유닉스 전동 공구

이 문제에 대해 알아둘 만한 또 다른 접근 방식이 있습니다(Unix Power Tools에도 설명되어 있음)."-exec를 사용하여 사용자 정의 테스트 만들기"):

find . -type f -exec sh -c 'file -b "$1" | grep -iqE "^ELF|^C source"' sh {} \; -print

이 필터링 방법은 파일 이름을 인쇄하는 것 이상의 용도로 사용할 수 있으므로 알아두는 것이 좋습니다. -print연산자를 원하는 다른 연산자(다른 -exec연산자 포함)로 변경하고 원하는 대로 수행하면 됩니다.


거기이 명령의 성능 결함(다음에도 나타남)또 다른 대답\;), 우리는 사용하고 있지 않기 때문에 +각 파일에 대해 쉘을 생성합니다. 한 번에 여러 파일을 명령 +에 전달 하고 루프를 사용하여 처리 하면 성능이 크게 향상됩니다 .shfor

find . -exec sh -c 'for f do file -b "$f" | grep -qE "^ELF|^C source" && printf %s\\n "$f"; done' sh {} +

다음 두 명령을 실행하고 출력을 비교하여 직접 비교 내용을 확인할 수 있습니다 time.

time find . -exec sh -c 'for f do file -b "$f" | grep -qE "^ELF|^C source" && printf %s\\n "$f"; done' sh {} +
time find . -exec sh -c 'file -b "$1" | grep -qE "^ELF|^C source" && printf %s\\n "$1"' sh {} \;

그러나 실제 요점은 다음과 같습니다.

for에서 출력되는 파일 목록에 대해 쉘 루프를 실행하지 마십시오 find.find대신 연산자를 사용하여 각 파일에서 수행해야 하는 작업을 직접 실행할 수 있습니다 -exec.포함시키다for루프이내에명령 하나만 find하면 됩니다.

몇 가지 추가 이유:

답변2

가장 간단한 방법은 각 파일에 대해 작은 스크립트를 실행하고 짧은 패턴 출력을 확인 file하고 출력이 file일치 ELF하거나 C source경로를 인쇄하면 경로가 에 전달되는 것입니다 $0.

find . -type f -exec sh -c \
    'file -b "$0" | grep -q "^ELF\|^C source" && printf %s\\n "$0"' {} \;

이 계획은 원래 계획에 비해 다음과 같은 장점이 있습니다.

-type f출력에 의존하는 대신 즉시 디렉터리를 필터링합니다.file

매개변수를 전달하면 {}파일 이름의 공백이나 개행과 관련된 문제를 피할 수 있습니다.

관련 정보