我知道我可以使用以下命令查找文件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
实用程序本身无法区分“shell 脚本”、“JPEG 图像文件”或任何其他文件常规文件类型。然而,这些类型的数据可以由实用程序来区分file
,该实用程序查看文件本身内的特定签名以确定文件内容的类型。
标记不同类型数据文件的常见方法是按其MIME类型,并且file
能够确定文件的 MIME 类型。
使用file
withfind
检测常规文件的 MIME 类型,并使用它来仅查找 shell 脚本:
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
将查找当前目录中或当前目录下的所有常规文件,并为每个此类文件调用一个简短的内联 shell 脚本。该脚本file -bi
在找到的文件上运行,如果该命令的输出包含字符串,则以零退出状态退出/x-shellscript
。如果输出不包含该字符串,它将以非零退出状态退出,这会导致find
立即继续下一个文件。如果发现该文件是 shell 脚本,该find
命令将继续输出文件的路径名(-print
末尾的 ,也可以由其他操作替换)。
该file -bi
命令将输出文件的 MIME 类型。对于 Linux(以及大多数其他系统)上的 shell 脚本,这将类似于
text/x-shellscript; charset=us-ascii
而在具有该实用程序稍旧版本的系统上file
,它可能是
application/x-shellscript
公共位是/x-shellscript
子串。
请注意,在 macOS 上,您必须使用file -bI
而不是file -bi
因为原因(该-i
选项的作用完全不同)。 macOS 上的输出在其他方面与 Linux 系统上的输出类似。
您想对每个找到的 shell 脚本执行一些自定义操作吗?您可以使用另一个脚本-exec
来代替上面-print
命令中的find
,但也可以这样做
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
不涉及太多 shell 魔法的较短形式:
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
。