システムまたは特定のディレクトリツリーですべてのスパースファイルを簡単に見つける方法はありますか?
関連している場合は、zsh
Ubuntu 12.04を使用していますが、bash / shに対するより一般的なUnix-yの答えは問題ありません。
編集する:明確に言えば、個々のファイルのスパース状態をチェックするのではなく、スパースファイルを探しています。
答え1
このフラグをサポートするSEEK_HOLE
lseek
システム(およびファイルシステム)(例:ext4のUbuntu 12.04)では、その値がSEEK_HOLE
Linuxのように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=C
10進基準が必要です(すべての実装がロケール設定を尊重するわけではありません)。.
awk
答え2
割り当てられたブロック数がファイルサイズより少ない場合、ファイルは一般的にまれです(ここではstat
Ubuntuで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)