7 maskfiles - Lay over several text files on top of each other like transparency sheets for overhead projectors
11 maskfiles [I<OPTIONS>] [--] I<FILE_1> I<FILE_2> [I<FILE_3> ... I<< FILE_B<n> >>]
15 Take files from 1 to B<n> and virtually put them on top of each other
16 by matching byte offsets.
17 If a file from the upper layer have a hole (space by default, otherwise see --hole-char option),
18 then the char on lower layers "looks through" it.
19 Non hole chars just block the lower layers, so they are visible at the end.
22 No input files are written.
28 =item -h, --hole-chars I<CHARS>
30 Which chars are to be looked through.
31 By default space is the only hole char.
32 Add underscore to it by example: --hole-chars=" _"
36 Make NUL chars to look through as well.
47 use Fcntl qw
/:flock :seek/;
48 use Getopt
::Long qw
/:config no_ignore_case no_bundling no_getopt_compat no_auto_abbrev require_order/;
51 no if ($] >= 5.018), 'warnings' => 'experimental::smartmatch';
59 'h|hole|holechar|hole-char|holechars|hole-chars=s' => \
$OptHoleChars,
60 'nul-hole' => \
$OptHoleNUL,
61 'l|linewise!' => \
$OptLinewise,
62 'help' => sub { pod2usage
(-exitval
=>0, -verbose
=>99); },
63 ) or pod2usage
(-exitval
=>2, -verbose
=>99);
66 $OptHoleChars .= chr(0) if $OptHoleNUL;
68 @overlay_files = @ARGV;
71 for my $path (reverse @overlay_files)
73 open my $fh, '<', $path or die "$0: open: $path: $!\n";
74 push @layers, {'fh'=>$fh, 'eol'=>0};
82 last if not grep {defined $_->{'fh'}} @layers;
84 if($OptLinewise and not grep {defined $_->{'fh'} and not $_->{'eol'}} @layers)
86 # all files are at EOL, reset flags
87 map {$_->{'eol'} = 0} @layers;
90 for my $layer (@layers)
92 my $fh = $layer->{'fh'};
93 next if not defined $fh;
94 next if $OptLinewise and $layer->{'eol'};
96 my $nbytes = read $fh, $char, 1;
99 $layer->{'fh'} = undef;
102 if($OptLinewise and $char eq "\n")
108 if(not defined $char0 and $OptHoleChars !~ /\Q$char\E/)
114 $char0 = $char if not defined $char0; # there are holes all the way down to the lowermost layer