find 명령의 -exec에서 두 개의 bash 명령을 사용하는 방법은 무엇입니까? GREP으로

find 명령의 -exec에서 두 개의 bash 명령을 사용하는 방법은 무엇입니까? GREP으로

나도 같은 일을하고 싶다find 명령의 -exec에서 두 개의 bash 명령을 사용하는 방법은 무엇입니까?그러나 두 번째 명령으로 grep을 사용하십시오. 이전 솔루션에 게시된 솔루션은 grep이 두 번째 명령인 경우 작동하지 않습니다. 또 다른 문제exec 옵션과 find 및 grep 명령의 조합grep 사용에 대해 질문했지만 모든 답변은 grep을 사용하지 않습니다. 제 생각엔 grep을 해야 할 것 같아요.

예를 들어,

sudo find -D exec . -maxdepth 1 -type f -iname "*" -exec file -N '{}' \; -exec echo 'asdf' \;

잘 작동하지만

sudo find -D exec . -maxdepth 1 -type f -iname "*" -exec file -N '{}' \; -exec grep "JPEG" {} \;

grep이 어떤 일을 한다는 증거는 없습니다. 첫 번째 명령의 표준 출력을 grep의 표준 입력으로 강제하려면 어떻게 해야 합니까? 대신, 파일 명령 출력을 파일로 파이프하고 해당 파일에 대해서만 grep을 실행하면 제대로 작동합니다.

dell@DELL-E6440:~$ rm junk.txt
dell@DELL-E6440:~$ sudo find -D exec . -maxdepth 1 -type f -iname "*" -exec file -N '{}' >> junk.txt \;
dell@DELL-E6440:~$ grep "JPEG" junk.txt
./150120-ssc-proxy~20190508-061623.jpg: JPEG image data, JFIF standard 1.01, resolution (DPI), density 150x150, segment length 16, baseline, precision 8, 1018x1426, frames 3
./avoid-powered-overfight~20190508-061623.jpg: JPEG image data, JFIF standard 1.01, aspect ratio, density 1x1, segment length 16, comment: "Intel(R) JPEG Library, version [2.0.16.48]", baseline, precision 8, 1048x659, frames 3
dell@DELL-E6440:~$

그러나 요점은 단일 bash 라인에서 이 작업을 수행하고 싶고 >>는 어쨌든 실행 사이에 파일을 적절하게 새로 고칠 수 없다는 것입니다.

답변1

file각 파일에서 실행하고 문자열을 grep출력 하려면 다음 을 수행하십시오 .fileJPEG

find . -maxdepth 1 -type f -exec file {} + | grep JPEG

file일반 파일 배치에서 작동하여 결과의 ​​출력 스트림을 생성합니다 . 그런 다음 스트림은 grep특정 문자열을 포함하는 행으로 필터링 됩니다 JPEG. 개행 문자가 포함된 파일 이름은 이 파이프의 출력에 잘못 표시됩니다.

문제의 명령은 명령 출력 grep이 아닌 파일 자체에서 실행됩니다 . 모든 파일 이름이 해당 조건자와 일치하므로 file명령 을 사용하면 아무 작업 find도 수행할 수 없습니다.-iname "*"

또는 bash현재 디렉터리의 파일에 대해 반복을 사용합니다.

shopt -s dotglob nullglob

for name in ./*; do
    mimetype=$( file --brief --mime-type "$name" )
    if [[ $mimetype == */jpeg ]]; then
        printf '"%s" is a JPEG file\n' "$name"
    fi
done

현재 디렉터리의 각 파일에 대해 보고된 MIME 유형을 사용하여 fileJPEG 파일에 해당하는 이름을 필터링합니다.

약간 확장된 예:

shopt -s dotglob nullglob

for name in ./*; do
    mimetype=$( file --brief --mime-type "$name" )
    case $mimetype in
        */jpeg)   printf '"%s" is a JPEG file\n'             "$name" ;;
        */png)    printf '"%s" is a PNG file\n'              "$name" ;;
        image/*)  printf '"%s" is some form of image file\n' "$name" ;;
        *)        printf '"%s" is not an image file\n'       "$name"
    esac
done

마지막으로 다음에서 직접 MIME 유형을 사용하십시오 find.

find . -maxdepth 1 -exec bash -c '[[ $(file -b --mime-type "$1") == */jpeg ]]' bash {} \; -print

또는 더 효과적으로,

find . -maxdepth 1 -exec bash -c '
    for pathname do
        [[ $(file -b --mime-type "$pathname") == */jpeg ]] && printf "%s\n" "$pathname"
    done' bash {} +

마지막 두 명령은 JPEG 이미지에 해당하는 경로 이름만 인쇄합니다.

답변2

쿠사의...-exec file {} + | grep ...

당신의find | file -f - | grep

이:

]# cat fhs.sh 
#/bin/bash
file -Nz * | grep "magic"

]# find . -exec ./fhs.sh {} +
uout: very short file (no magic)

동일한 타이밍을 사용하면 모든 것이 작동하는 것 같습니다. 다른 변형도 작동하지만 시간이 더 오래 걸립니다.


일반적으로 이 find ... -exec grep xxx {} +구성은 매우 잘 작동합니다( +아님 \;). 하지만 여기서는 을 사용하여 file파일 이름을 "간섭"할 수 있습니다.

따라서 여기서는 "플랫"(파이프라인) 접근 방식이 괜찮습니다.

답변3

두 개의 명령을 find 명령에 포함시키는 것은 최선의 생각이 아닙니다. 대신, find에서 두 작업의 압축을 풀고 파이프라인을 통해 정렬합니다.

$ sudo find . -type f | file -Nz -f - | grep -f ~/badtypes.txt

이제 file 명령을 사용하여 이름이 바뀌었거나 압축되었는지 여부에 관계없이 컴퓨터에 속하지 않는 모든 종류의 파일을 반복적으로 찾을 수 있는 방법이 제공됩니다. file 명령에 자연스럽게 재귀 옵션이 없는 이유가 궁금합니다.

관련 정보