http://qs321.pair.com?node_id=716338


in reply to system and &>/dev/null

Does someone know how to create sparse files with Perl without using a system command?
How about this:
open my $fh, '>', 'zeros' or die "error opening fh: ($!)"; binmode $fh; print $fh pack "x512"; #512 bytes-- season to taste, loop as needed

Replies are listed 'Best First'.
Re^2: system and &>/dev/null
by duelafn (Parson) on Oct 10, 2008 at 02:21 UTC

    Doesn't seem to create a sparse file:

    [tmp]$ cat broomduster.pl open my $fh, '>', 'zeros' or die "error opening fh: ($!)"; binmode $fh; print $fh pack "x".(1024*1024*10); [tmp]$ rm zeros; perl broomduster.pl; ls -lh zeros; du -h zeros -rw-rw-r-- 1 duelafn 10M 2008-10-09 22:17 zeros 11M zeros

    However, the following works:

    [tmp]$ cat duelafn.pl open my $fh, '>', 'zeros' or die "error opening fh: ($!)"; seek $fh, 1024*1024*10 - 1, 0; print $fh "\0"; [tmp]$ rm zeros; perl duelafn.pl; ls -lh zeros; du -h zeros -rw-rw-r-- 1 duelafn 10M 2008-10-09 22:17 zeros 12K zeros

    Good Day,
        Dean

      This would not create a 100% sparse file because the last block would be all zero (even you print only one zero). Fletch was right in his above post, the combination of seek and truncate must be used.

      Here my first attempt from yesterday evening to create a halfway secure sub function which doesn't mess-up existing files:

      sub create_sparse { my ($file, $size) = @_; return if -e $file && ! -f _; return -2 if -e _ && -s _ >= $size; open my $fh, '+>', $file or return; eval { seek $fh, $size, 0 or die; truncate $fh, $size or die; } or do { close $fh; return; }; close $fh or return; return -1; }
        Just curious:
        • Why the need for seek when you're just going to close $fh after truncate?
        • Please expain the eval - close $fh - return logic you're using.