나도 같은 일을하고 싶다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
출력 하려면 다음 을 수행하십시오 .file
JPEG
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 유형을 사용하여 file
JPEG 파일에 해당하는 이름을 필터링합니다.
약간 확장된 예:
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 명령에 자연스럽게 재귀 옵션이 없는 이유가 궁금합니다.