파일 유형별로 파일을 찾는 방법은 무엇입니까?

파일 유형별로 파일을 찾는 방법은 무엇입니까?

다음을 사용하여 파일을 찾을 수 있다는 것을 알고 있습니다 find. find . -type f -name 'sunrise'결과 예:

./sunrise
./events/sunrise
./astronomy/sunrise
./schedule/sunrise

또한 파일의 파일 형식을 결정할 수 있다는 것도 알고 있습니다. file sunrise결과 예:

sunrise: PEM RSA private key

하지만 파일 유형별로 파일을 찾는 방법은 무엇입니까?

예를 들어, my-find . -type f -name 'sunrise' -filetype=bash-script:

./astronomy/sunrise
./schedule/sunrise

답변1

Unix 시스템의 "파일 형식"일반 파일, 디렉토리, 명명된 파이프, 문자 특수 파일, 심볼릭 링크 등 find해당 옵션을 사용하여 필터링할 수 있는 파일 형식은 다음과 같습니다 -type.

유틸리티 find자체는 "셸 스크립트", "JPEG 이미지 파일" 또는 기타 파일을 구별할 수 없습니다.일반 파일 형식. 그러나 이러한 유형의 데이터는 file파일 콘텐츠 유형을 결정하기 위해 파일 자체 내의 특정 서명을 살펴보는 유틸리티로 구별할 수 있습니다 .

다양한 유형의 데이터 파일에 레이블을 지정하는 일반적인 방법은MIME 유형, file파일의 MIME 유형을 결정할 수 있습니다.


일반 파일의 MIME 유형을 감지하고 이를 사용하여 쉘 스크립트만 찾으려면 filewith를 사용하십시오 .find

find . -type f -exec sh -c '
    case $( file -bi "$1" ) in (*/x-shellscript*) exit 0; esac
    exit 1' sh {} \; -print

또는 bash,

find . -type f -exec bash -c '
    [[ "$( file -bi "$1" )" == */x-shellscript* ]]' bash {} \; -print

해당 이름의 스크립트만 탐지하려면 -name sunrise앞에 추가하세요.-exec

위의 명령은 find현재 디렉토리 안이나 아래의 모든 일반 파일을 찾고 그러한 각 파일에 대해 짧은 인라인 쉘 스크립트를 호출합니다. 스크립트는 file -bi발견된 파일에서 실행되고 명령 출력에 strings 가 포함된 경우 종료 상태 0으로 종료됩니다 /x-shellscript. 출력에 이 문자열이 포함되어 있지 않으면 0이 아닌 종료 상태로 종료되어 find다음 파일로 즉시 계속됩니다. 파일이 쉘 스크립트인 것으로 확인되면 find명령은 계속해서 파일의 경로 이름을 출력합니다( -print마지막 경로는 다른 작업으로 대체될 수도 있음).

file -bi명령은 파일의 MIME 유형을 출력합니다. Linux(및 대부분의 다른 시스템)의 쉘 스크립트의 경우 이는 다음과 같습니다.

text/x-shellscript; charset=us-ascii

이 유틸리티의 약간 오래된 버전이 설치된 시스템에서는 file다음과 같은 문제가 발생할 수 있습니다.

application/x-shellscript

공통 비트는 /x-shellscript부분 문자열입니다.

file -bImacOS에서는 대신 사용해야 합니다 file -bi.이유(이 -i옵션은 완전히 다른 기능을 수행합니다). macOS의 출력은 Linux 시스템의 출력과 유사합니다.


발견된 각 쉘 스크립트에 대해 몇 가지 사용자 정의 작업을 수행하시겠습니까? 위 명령 -exec대신 다른 스크립트를 사용할 수도 있지만 다음을 수행할 수도 있습니다.-printfind

find . -type f -exec sh -c '
    for pathname do
        case $( file -bi "$pathname" ) in
            */x-shellscript*) ;;
            *) continue
        esac

        # some code here that acts on "$pathname"

    done' sh {} +

또는 bash,

find . -type f -exec bash -c '
    for pathname do
        [[ "$( file -bi "$pathname" )" != */x-shellscript* ]] && continue

        # some code here that acts on "$pathname"

    done' bash {} +

관련된:

답변2

발견된 각 파일을 실행 file한 다음 grep을 통해 관심 있는 결과를 얻을 수 있습니다.

# When looking for ASCII Text
find . -type f -exec file {} \; | grep "ASCII"
# or for MS Word Documents
find . -type f -exec file {} \; | grep "Microsoft Word"

잘못된 긍정 일치 수를 낮게 유지하려면 검색 패턴을 예상에 최대한 가깝게 유지하는 것이 좋습니다.

이름에 줄 바꿈이 포함된 파일은 이 방법에서 문제를 일으킬 수 있습니다.

답변3

쉘 마법을 너무 많이 포함하지 않는 더 짧은 형식:

find . -exec sh -c "file '{}' | grep -q 'pattern'" \; -print

답변4

사용된 perl모듈 File::LibMagic:

perl -MFile::LibMagic=:easy -MFile::Find -le '
  find sub {
    print $File::Find::name if
      $_ eq "sunrise" and
      -f and
      MagicFile$_ eq "PEM RSA private key"
  }, @ARGV' -- .

File::LibMagic동일한 알고리즘과 휴리스틱을 사용하여 파일 유형을 추측 file하지만 여기서는 모든 것이 단일 호출로 수행되므로 perl각 파일에 대해 단일 호출을 실행하는 것보다 훨씬 효율적입니다 file.

관련 정보