如何在 find 命令的 -exec 中使用两个 bash 命令?与GREP

如何在 find 命令的 -exec 中使用两个 bash 命令?与GREP

我想做同样的事如何在 find 命令的 -exec 中使用两个 bash 命令?但用 grep 作为第二个命令。当 grep 是第二个命令时,为先前的解决方案发布的解决方案不起作用。另一个问题find 和 grep 命令与 exec 选项的组合询问是否使用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 "*"which 是一个无操作,因为所有文件名都与该谓词匹配。

或者,使用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 命令自然没有递归选项。

相关内容