web-dev-qa-db-ja.com

ファイルの種類でファイルを見つける方法は?

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
9
Flux

NIXシステムの「ファイルタイプ」 は、通常のファイル、ディレクトリ、名前付きパイプ、文字特殊ファイル、シンボリックリンクなどです。これらは、findがフィルタリングできるファイルのタイプです-typeオプション付き。

findユーティリティ自体では、「シェルスクリプト」、「JPEG画像ファイル」、またはその他のタイプの通常のファイルを区別できません。ただし、これらのタイプのデータはfileユーティリティによって区別される場合があります。このユーティリティは、ファイル内の特定の署名を調べてタイプを判別します。

さまざまなタイプのデータファイルにラベルを付ける一般的な方法は、それらの MIMEタイプ によるものであり、fileはファイルのMIMEタイプを判別できます。


filefindとともに使用して、通常のファイルのMIMEタイプを検出し、それを使用してシェルスクリプトのみを検索します。

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コマンドは、現在のディレクトリ内またはその下にあるすべての通常のファイルを検索し、そのようなファイルごとに短いインラインシェルスクリプトを呼び出します。このスクリプトは、見つかったファイルに対してfile -biを実行し、そのコマンドの出力に文字列/x-shellscriptが含まれている場合、ゼロの終了ステータスで終了します。出力にその文字列が含まれていない場合、出力は0以外の終了ステータスで終了し、findは次のファイルをすぐに続行します。ファイルがシェルスクリプトであることが判明した場合、findコマンドはファイルのパス名(最後の-printを出力しますが、他のアクションで置き換えることもできます)に進みます。

file -biコマンドは、ファイルのMIMEタイプを出力します。 Linux(および他のほとんどのシステム)のシェルスクリプトの場合、これは次のようになります。

text/x-shellscript; charset=us-ascii

少し古いバージョンのfileユーティリティがインストールされているシステムでは、

application/x-shellscript

一般的なビットは/x-shellscriptサブストリングです。

理由のため、macOSではfile -bIの代わりにfile -biを使用する必要があることに注意してください(-iオプションはまったく異なることをします) 。 macOSの出力はLinuxシステムの出力に似ています。


見つかった各シェルスクリプトでカスタムアクションを実行したい場合は、上記のfindコマンドの-execの代わりに別の-printを使用して実行できますが、できる

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 {} +

関連:

13
Kusalananda

見つかったすべてのファイルに対してfindを実行してから、興味のある結果をgrepできます。

# When looking for ASCII Text
find . -type -exec file {} \; | grep "ASCII"
# or for MS Word Documents
find . -type f -exec file {} \; | grep "Microsoft Word"

誤検出の数を低く抑えるために、検索パターンをできるだけ期待に近づけることをお勧めします。

ファイル名に改行が含まれているファイルは、このアプローチで問題を引き起こす可能性があることに注意してください。

1
Rolf

PerlFile::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' -- .
0