ファイルがある場合
#!/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スパースファイルの場合、ほとんどのシェルでは時間がかかり、メモリも多用されます。
これ以外のシェルの場合は、zsh
NULで始まり、次の文字に応答することもできます#!
。
シェルの場合、yash
shebangに現在のロケールで有効な文字を形成しないバイトシーケンスが含まれていると失敗します(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=raw
perl
IOバッファリング層なしでシステムコールを直接使用できるようにするためread()
(ファイル名の印刷にも影響します)、サイズ2の読み取りを実行します。$/ = \2
レコード区切り文字が数値への参照に設定されている場合、レコードは固定長レコードになります。close ARGV
最初のレコードを読み取った後、現在のファイルの残りの部分をスキップします。