我想做同样的事如何在 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 命令自然没有递归选项。