まれなファイルをお探しですか?

まれなファイルをお探しですか?

システムまたは特定のディレクトリツリーですべてのスパースファイルを簡単に見つける方法はありますか?

関連している場合は、zshUbuntu 12.04を使用していますが、bash / shに対するより一般的なUnix-yの答えは問題ありません。

編集する:明確に言えば、個々のファイルのスパース状態をチェックするのではなく、スパースファイルを探しています。

答え1

このフラグをサポートするSEEK_HOLE lseekシステム(およびファイルシステム)(例:ext4のUbuntu 12.04)では、その値がSEEK_HOLELinuxのように4であるとします。

if perl -le 'seek STDIN,0,4;$p=tell STDIN;
   seek STDIN,0,2; exit 1 if $p == tell STDIN'< the-file; then
  echo the-file is sparse
else
  echo the-file is not sparse
fi

シェル構文はPOSIXです。内部に持ち運べないものはperlこんな感じですSEEK_HOLE

lseek(SEEK_HOLE)最初のスタートを探しています。ファイルに存在する場合、または脆弱性が見つからない場合は、ファイルの末尾にあります。上記では、lseek(SEEK_HOLE)ファイルの末尾(同じ場所)に移動したときにファイルがリーンではないことがわかりますlseek(SEEK_END)

スパースファイルを一覧表示するには:

find . -type f ! -size 0 -exec perl -le 'for(@ARGV){open(A,"<",$_)or
  next;seek A,0,4;$p=tell A;seek A,0,2;print if$p!=tell A;close A}' {} +

GNU find(バージョン4.3.3以降)は-printf %S報告する必要があります。希少性ファイルの。それを使うフロストスーツの答えディスク使用量とファイルサイズの比率を考慮しているため、すべてのスパースファイル属性を報告することを保証することはできません(たとえば、ファイルシステムレベルで圧縮が行われた場合、またはホールセーブがファイルシステムインフラストラクチャオーバーヘッドを補償できない場合、または大容量拡張ファイルの場合))、実装されていないシステム、または実装されていないファイルSEEK_HOLEシステムで動作します。SEEK_HOLEここにGNUツールがあります:

LC_ALL=C find . -type f ! -size 0 -printf '%S:%p\0' |
  LC_ALL=C awk -v RS='\0' -F : '$1 < 1 {sub(/^[^:]*:/, ""); print}'

find(この回答の以前のバージョンは、3.2e-05のように希少性を表現したときに正しく機能しませんでした。ありがとうございます。@flashydaveからの返信私の注目を集めた。ロケール基準の代わりにLC_ALL=C10進基準が必要です(すべての実装がロケール設定を尊重するわけではありません)。.awk

答え2

割り当てられたブロック数がファイルサイズより少ない場合、ファイルは一般的にまれです(ここではstatUbuntuでGNUを使用しますが、他のシステムには互換性のない実装がある可能性があることに注意してくださいstat)。

if [ "$((`stat -c '%b*%B-%s' -- "$file"`))" -lt 0 ]
then
    echo "$file" is sparse
else
    echo "$file" is not sparse
fi

変形find:(ステファンから盗む)

find . -type f ! -size 0 -exec bash -c '
    for f do
        [ "$((`stat -c "%b*%B-%s" -- "$f"`))" -lt 0 ] && printf "%s\n" "$f";
    done' {} +

通常、これをシェルスクリプトに入れてからシェルスクリプトを実行します。

find . -type f ! -size 0 -exec ./sparsetest.sh {} +

答え3

%S次の形式のスパースファイルがありますfind

# find / -type f -printf "%S\t%p\n" | gawk '$1 < 1.0 {print}'
0.0139994       /var/log/lastlog
0.959592        /usr/lib/locale/locale-archive
...

この記事で見つかった内容: https://www.thegeekdiary.com/how-to-find-all-the-sparse-file-in-linux/

答え4

脆弱性がファイルのどこにあるかを調べようとしながら、作成した短いスクリプトは次のとおりです。

#!/usr/bin/python3
import os
import sys
import errno

def report(fname):
    fd = os.open(fname, os.O_RDONLY)
    len = os.lseek(fd, 0, os.SEEK_END)
    offset = 0
    while offset < len:
        start = os.lseek(fd, offset, os.SEEK_HOLE)
        if start == len:
            break
        try:
            offset = os.lseek(fd, start, os.SEEK_DATA)
        except OSError as e:
            if e.errno == errno.ENXIO:
                offset = len
            else:
                raise
        print(f'found hole between 0x{start:08X} and 0x{offset:08X} ({offset - start} bytes)')

if __name__ == '__main__':
    for name in sys.argv[1:]:
        report(name)

これにより、次のように印刷されます。

$ echo -n 'a' >zeros; truncate -s $((4096*4)) zeros; test/report-holes.py zeros
found hole between 0x00001000 and 0x00004000 (12288 bytes)

関連情報