shebangが存在することを確認する最速の方法

shebangが存在することを確認する最速の方法

ファイルがある場合

#!/usr/bin/env foobar

ファイルにハッシュバンがあることを確認するための最速かつ最善の方法は何ですか?最初の2バイトしか読めないと聞きましたが?どのように?

ベストアンサー1

そしてzsh

if LC_ALL=C read -u0 -k2 shebang < file && [ "$shebang" = '#!' ]; then
  echo has shebang
fi

またはksh93と同じbash

if IFS= LC_ALL=C read -rN2 shebang < file && [ "$shebang" = '#!' ]; then
  echo has shebang
fi

ただし、NULで始まり、その後にandが続くファイルにbash誤検出が発生します。#!みんなtruncate -s1T fileたとえば、先行する NUL バイトは一度に 2 バイトで生成された 1 TB ファイルを読み込みます。

したがって、bash以下を使用することをお勧めします。

IFS= LC_ALL=C read -rn2 -d '' shebang

私が読んだのはまさにそれです。に従って2バイトのNULで区切られたレコード。

read[コマンドがecho組み込まれているため、プロセスをフォークしたり、追加のコマンドを実行したりしません。

POSIXlyでは、次のことができます。

if IFS= read -r line < file; then
  case $line in
    ("#!"*) echo has shebang
  esac
fi

完全なラインも必要なので、より厳しいです。少なくともLinuxでは、有効なshebangに改行文字は必要ありません。

だからあなたはこれを行うことができます:

line=
IFS= read -r line < file
case $line in
  ("#!"*) echo has shebang
esac

より多くのバイトを読み取ることができるため、少し効率が悪くなりますが、一部のシェルは一度に1バイトしか読み取れません。 1TiBスパースファイルの場合、ほとんどのシェルでは時間がかかり、メモリも多用されます。

これ以外のシェルの場合は、zshNULで始まり、次の文字に応答することもできます#!

シェルの場合、yashshebangに現在のロケールで有効な文字を形成しないバイトシーケンスが含まれていると失敗します(shebangにCロケール(少なくとも2.39以前)でASCII以外の文字が含まれている場合でも失敗します。 Cロケールは、すべての文字が単一バイトで、すべてのバイト値が有効な(必ずしも定義されていない場合)文字を形成することを意味しますが)

内容が で始まるすべてのファイルを検索するには、#!次のようにします。

PERLIO=raw find . -type f -size +4c -exec perl -T -ne '
  BEGIN{$/=\2} print "$ARGV\n" if $_ eq "#!"; close ARGV' {} +

サイズが最小5バイト(#!/x\n最小で現実的なshebang)のファイルのみを考慮します。

  • を使用して-exec perl... {} +できるだけ多くのファイルパスを渡すので、perlできるだけ少ない呼び出しを実行します。
  • -T解決される予定です限界perl -nまた、ASCIIスペース文字または.で終わる名前には機能しないことを意味します|
  • PERLIO=rawperlIOバッファリング層なしでシステムコールを直接使用できるようにするためread()(ファイル名の印刷にも影響します)、サイズ2の読み取りを実行します。
  • $/ = \2レコード区切り文字が数値への参照に設定されている場合、レコードは固定長レコードになります。
  • close ARGV最初のレコードを読み取った後、現在のファイルの残りの部分をスキップします。

おすすめ記事