如何按文件类型查找文件?

如何按文件类型查找文件?

我知道我可以使用以下命令查找文件findfind . -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 类型。


使用filewithfind检测常规文件的 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

相关内容