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

Flu*_*lux 13 find file-command files file-types

我知道我可以使用find:找到文件find . -type f -name 'sunrise'。结果示例:

./sunrise
./events/sunrise
./astronomy/sunrise
./schedule/sunrise
Run Code Online (Sandbox Code Playgroud)

我也知道我可以确定文件的文件类型:file sunrise. 结果示例:

sunrise: PEM RSA private key
Run Code Online (Sandbox Code Playgroud)

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

例如my-find . -type f -name 'sunrise' -filetype=bash-script

./astronomy/sunrise
./schedule/sunrise
Run Code Online (Sandbox Code Playgroud)

Kus*_*nda 19

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
Run Code Online (Sandbox Code Playgroud)

或者,使用bash

find . -type f -exec bash -c '
    [[ "$( file -bi "$1" )" == */x-shellscript* ]]' bash {} \; -print
Run Code Online (Sandbox Code Playgroud)

如果您只想检测具有该名称的脚本,请-name sunrise在 之前添加-exec

find上面的命令将查找当前目录中或以下的所有常规文件,并为每个此类文件调用一个简短的内嵌 shell 脚本。该脚本file -bi在找到的文件上运行,如果该命令的输出包含字符串,则以零退出状态退出/x-shellscript。如果输出不包含该字符串,它将以非零退出状态退出,这会导致find立即继续下一个文件。如果发现该文件是一个 shell 脚本,该find命令将继续输出文件的路径名(-print末尾的 ,也可以由其他一些操作替换)。

file -bi命令将输出文件的 MIME 类型。对于 Linux(和大多数其他系统)上的 shell 脚本,这将类似于

text/x-shellscript; charset=us-ascii
Run Code Online (Sandbox Code Playgroud)

而在具有该file实用程序稍旧变体的系统上,它可能是

application/x-shellscript
Run Code Online (Sandbox Code Playgroud)

公共位是/x-shellscript子串。

请注意,在 macOS 上,由于原因,您必须使用file -bI而不是(该选项的作用完全不同)。macOS 上的输出在其他方面类似于 Linux 系统的输出。file -bi-i


您是否想对每个找到的 shell 脚本执行一些自定义操作,您可以使用另一个-exec来代替上面-printfind命令,但也可以这样做

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 {} +
Run Code Online (Sandbox Code Playgroud)

或者,用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 {} +
Run Code Online (Sandbox Code Playgroud)

有关的: