use 5.6.2 ;
use strict;
+use warnings ;
use Carp ;
use Exporter ;
use Fcntl qw( :DEFAULT ) ;
use POSIX qw( :fcntl_h ) ;
-use Symbol ;
+#use Symbol ;
use vars qw( @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $VERSION ) ;
@ISA = qw( Exporter ) ;
#printf "RD: BINARY %x MODE %x\n", O_BINARY, $mode ;
- $read_fh = gensym ;
+ $read_fh = local( *FH ) ;
+# $read_fh = gensym ;
unless ( sysopen( $read_fh, $file_name, $mode ) ) {
@_ = ( $opts, "read_file '$file_name' - sysopen: $!");
goto &_error ;
}
}
-
-# if ( $size_left < 10000 && keys %{$opts} == 0 && !wantarray ) {
-
-# my $read_cnt = sysread( $read_fh, my $buf, $size_left ) ;
-
-# unless ( defined $read_cnt ) {
-
-# @_ = ( $opts, "read_file '$file_name' - small2 sysread: $!");
-# goto &_error ;
-# }
-
-# return $buf ;
-# }
-
# infinite read loop. we exit when we are done slurping
while( 1 ) {
my @lines = length(${$buf_ref}) ?
${$buf_ref} =~ /(.*?$sep|.+)/sg : () ;
+ chomp @lines if $opts->{'chomp'} ;
+
# caller wants an array ref
return \@lines if $opts->{'array_ref'} ;
# open the file and handle any error.
- $write_fh = gensym ;
+ $write_fh = local( *FH ) ;
+# $write_fh = gensym ;
unless ( sysopen( $write_fh, $file_name, $mode, $perms ) ) {
@_ = ( $opts, "write_file '$file_name' - sysopen: $!");
@dir_entries = grep( $_ ne "." && $_ ne "..", @dir_entries )
unless $opts->{'keep_dot_dot'} ;
+ if ( $opts->{'prefix'} ) {
+
+ substr( $_, 0, 0, "$dir/" ) for @dir_entries ;
+ }
+
return @dir_entries if wantarray ;
return \@dir_entries ;
}
use File::Slurp;
# read in a whole file into a scalar
-
my $text = read_file( 'filename' ) ;
# read in a whole file into an array of lines
-
my @lines = read_file( 'filename' ) ;
# write out a whole file from a scalar
-
write_file( 'filename', $text ) ;
# write out a whole file from an array of lines
-
write_file( 'filename', @lines ) ;
# Here is a simple and fast way to load and save a simple config file
# made of key=value lines.
-
my %conf = read_file( $file_name ) =~ /^(\w+)=(\.*)$/mg ;
write_file( $file_name, {atomic => 1}, map "$_=$conf{$_}\n", keys %conf ;
# insert text at the beginning of a file
-
prepend_file( 'filename', $text ) ;
-# read in a whole directory of file names (skipping . and ..)
+# in-place edit to replace all 'foo' with 'bar' in file
+ edit_file { s/foo/bar/g } 'filename' ;
+# in-place edit to delete all lines with 'foo' from file
+ edit_file_lines sub { $_ = '' if /foo/ }, 'filename' ;
+
+# read in a whole directory of file names (skipping . and ..)
my @files = read_dir( '/path/to/dir' ) ;
=head1 DESCRIPTION
my $lines_ref = read_file( $bin_file, array_ref => 1 ) ;
my $lines_ref = [ read_file( $bin_file ) ] ;
+=head3 chomp
+
+If this boolean option is set, the lines are chomped. This only
+happens if you are slurping in a list context or using the
+C<array_ref> option.
+
=head3 scalar_ref
If this boolean option is set, the return value (only in scalar
prepend_file( $file, \@lines ) ;
prepend_file( $file, { binmode => 'raw:'}, $bin_data ) ;
+
+=head2 edit_file, edit_file_lines
+
+These subs read in a file into $_, execute a code block which should
+modify $_ and then write $_ back to the file. The difference between
+them is that C<edit_file> reads the whole file into $_ and calls the
+code block one time. With C<edit_file_lines> each line is read into $_
+and the code is called for each line. In both cases the code should
+modify $_ if desired and it will be written back out. These subs are
+the equivilent of the -pi command line options of Perl but you can
+call them from inside your program and not fork out a process.
+
+The first argument to C<edit_file> and C<edit_file_lines> is a code
+block or a code reference. The code block is not followed by a comma
+(as with grep and map) but a code reference is followed by a
+comma. See the examples below for both styles. The next argument is
+the filename. The last argument is an optional hash reference and it
+contains key/values that can modify the behavior of
+C<prepend_file>.
+
+Only the C<binmode> and C<err_mode> options are supported. The
+C<write_file> call has the C<atomic> option set so you will always
+have a consistant file. See above for more about those options.
+
+Each group of calls below show a Perl command line instance and the
+equivilent calls to C<edit_file> and C<edit_file_lines>.
+
+ perl -0777 -pi -e 's/foo/bar/g' filename
+ use File::Slurp ;
+ edit_file { s/foo/bar/g } 'filename' ;
+ edit_file sub { s/foo/bar/g }, 'filename' ;
+ edit_file \&replace_foo, 'filename' ;
+ sub replace_foo { s/foo/bar/g }
+
+ perl -pi -e '$_ = '' if /foo/' filename
+ use File::Slurp ;
+ edit_file_lines { $_ = '' if /foo/ } 'filename' ;
+ edit_file_lines sub { $_ = '' if /foo/ }, 'filename' ;
+ edit_file \&delete_foo, 'filename' ;
+ sub delete_foo { $_ = '' if /foo/ }
+
=head2 read_dir
This sub reads all the file names from directory and returns them to
my @all_files = read_dir( '/path/to/dir', keep_dot_dot => 1 ) ;
+=head3 prefix
+
+If this boolean option is set, the string "$dir/" is prefixed to each
+dir entry. This means you can directly use the results to open
+files. A common newbie mistake is not putting the directory in front
+of entries when opening themn.
+
+ my @paths = read_dir( '/path/to/dir', prefix => 1 ) ;
+
=head2 EXPORT
read_file write_file overwrite_file append_file read_dir