hack のためのネタ帳, etc,,,

データのない部分について、ディスクへの割り当てを省略することで、ディスク容量を節約しているファイル

作り方(Windows系の場合)

fsutil コマンドの sparse サブコマンドを使うと良いらしい。

作り方(UNIX系の場合)

dd コマンドで spase file を作るには以下のように、count=0 にして bs と seek でファイルサイズを調整すれば良い。
if=/dev/zero は付けた方が行儀は良いが、どうせ count=0 なのでなくても問題ない(/dev/stdin から 0 バイト読まれる事になる)。
dd of=sparse.dat count=0 bs=1 seek=1MiB

アクセス方法による違い

アクセス方法により対応できない場合がある模様
例えば dd を使って IO-DATA HDL-XR へ書き込んだ場合以下のようになった。
Windows7 + cygwin//LANDISK/hoge
Ubuntu 12.04 LTSmount.cifs //LANDISK/hoge /mnt/hoge
Ubuntu 12.04 LTSgvfs-mount smb://LANDISK/hoge×
gvfs 経由だと ls -s による割り当てサイズ表示も上手く処理されない模様
ただし gvfs 経由でも C や Ruby から seek して書き込んだ場合、内部的には sparse file になっている模様

既存の非スパースファイルのスパース化

割り当て済みのブロックを解放して穴を空けるので hole-punching (穴空け)と言う言い方をするらしい。
Linux の場合は、fallocate(2) システムコールに FALLOC_FL_PUNCH_HOLE フラグを与えれば良いらしい。
参考: その他の UNIX 系でのやり方は不明。
Windows だと fsutil sparse に setrange パラメータを与えると同様のことが出来そうなので、多分対応する API があるはず(要調査)。
cp や rsync に sparse 用のオプションを付けてコピーし直すだけで良さそう。
但し、cygwin で NTFS 上だとデフォルトでは上手く行かない模様。
/cygdrive/c の mount に sparse オプション付ければ大丈夫か???
例えば、以下の様なコマンドを実行してみると次のような結果が得られる。
(
  uname -srvmo
  type lsb_release &>/dev/null && lsb_release -d || echo "no lsb_release"
  dd if=/dev/zero of=sparse bs=1M count=0 seek=100 &>/dev/null
  dd if=/dev/zero of=zero bs=1M count=100 &>/dev/null
  cp -a --sparse=always zero zero.sparse.cp
  rsync -Sa zero zero.sparse.rsync
  cat zero | cp --sparse=always /dev/stdin zero.sparse.cp_with_stdin
  cat zero | rsync -S /dev/stdin zero.sparse.rsync_with_stdin
  ls -lsh
)

Cygwin の /tmp/sparsetest (ntfs) 上

CYGWIN_NT-6.1 2.4.1(0.293/5/3) 2016-01-24 11:26 x86_64 Cygwin
no lsb_release
skipping non-regular file "stdin"
total 500M
100M -rw-r--r-- 1 kou None 100M Mar  4 21:21 sparse
100M -rw-r--r-- 1 kou None 100M Mar  4 21:21 zero
100M -rw-r--r-- 1 kou None 100M Mar  4 21:21 zero.sparse.cp
100M -rw------- 1 kou None 100M Mar  4 21:21 zero.sparse.cp_with_stdin
100M -rw-r--r-- 1 kou None 100M Mar  4 21:21 zero.sparse.rsync

Cygwin の /cygdrive/l/sparsetest (smbfs) 上

CYGWIN_NT-6.1 2.4.1(0.293/5/3) 2016-01-24 11:26 x86_64 Cygwin
no lsb_release
skipping non-regular file "stdin"
total 100M
   0 -rwxrw-rw- 1 Unknown+User Unix_Group+100 100M Mar  4 21:21 sparse
100M -rwxrw-rw- 1 Unknown+User Unix_Group+100 100M Mar  4 21:21 zero
   0 -rw-rw-rw- 1 Unknown+User Unix_Group+100 100M Mar  4 21:21 zero.sparse.cp
   0 -rwxrw-rw- 1 Unknown+User Unix_Group+100 100M Mar  4  2016 zero.sparse.cp_with_stdin
   0 -rwxrw-rw- 1 Unknown+User Unix_Group+100 100M Mar  4 21:21 zero.sparse.rsync

Ubuntu の /tmp/sparsetest (NTFS) 上

Linux 3.13.0-74-generic #118-Ubuntu SMP Thu Dec 17 22:52:10 UTC 2015 x86_64 GNU/Linux
Description:	Ubuntu 14.04.4 LTS
skipping non-regular file "stdin"
合計 101M
100K -rw-rw-r-- 1 kou kou 100M  3月  4 21:21 sparse
101M -rw-rw-r-- 1 kou kou 100M  3月  4 21:21 zero
100K -rw-rw-r-- 1 kou kou 100M  3月  4 21:21 zero.sparse.cp
100K -rw------- 1 kou kou 100M  3月  4 21:21 zero.sparse.cp_with_stdin
100K -rw-rw-r-- 1 kou kou 100M  3月  4 21:21 zero.sparse.rsync
rsync はデフォルトだと /proc/self/fd/0 を処理しないようだ。

参考:
find コマンドで %S が 1.0 以下の物を探せば良いらしい。
詳細は find の man page 参照。
find . -type f -printf "%S\t%p\n" | awk -vFS="\t" '{if ($1<1.0) print $2}'
参考:
タグ

コメントをかく


「http://」を含む投稿は禁止されています。

利用規約をご確認のうえご記入下さい

Wiki内検索

フリーエリア

管理人/副管理人のみ編集できます