Reputation: 984
I need to
Read a list of the files from in a specified directory
Create an array of hashes describing those files
My program fetches the path to a directory from the command line, opens it and reads its contents. Directories and "dot" files are skipped, and the absolute path to every other entry is printed.
use strict;
use warnings;
use Data::Dumper qw(Dumper);
use File::Spec;
use Digest::SHA qw(sha256_hex);
my $dir = $ARGV[0];
opendir DIR, $dir or die "cannot open dir $dir: $!";
while ( my $file = readdir DIR ) {
next unless ( -f "${ \File::Spec->catfile($dir, $file) }" );
next if ( "$file" =~ m/^\./) ;
print "${ \File::Spec->rel2abs($file) }\n";
}
closedir DIR;
Here I take a single file and create a hash with the path, size, and sha256sum.
my $file = "file1.txt";
my @fileref = (
{
path => "Full path: " . File::Spec->rel2abs($file),
size => "Size (bytes): " . -s $file,
id => "SHA256SUM: " . sha256_hex($file),
},
);
print "\n";
print "$fileref[0]{path}\n";
print "$fileref[0]{size}\n";
print "$fileref[0]{id}\n";
All of this works, but I cannot figure out how to iterate over each file and add it to the array.
This is what I planned
for each file
push file into array
add the path, size, and id key:value pairs to file
repeat
How can I generate the necessary array?
Upvotes: 1
Views: 208
Reputation: 126722
Here's my approach to a solution. I've saved a lot of code by using File::Spec::Functions
instead of File::Spec
, and calling rel2abs
only once
I've also removed the labels, like "Full path: "
, from the values in the hashes. There's no reason to put presentation strings in there: that's for the output code to do
use strict;
use warnings;
use File::Spec::Functions qw/ catfile rel2abs /;
use Digest::SHA qw/ sha256_hex /;
use Data::Dumper qw/ Dumper /;
my ( $root ) = @ARGV;
$root = rel2abs( $root ); # Allow for relative path input
my @file_data;
{
opendir my $dh, $root or die qq{Cannot open directory "$root": $!};
while ( readdir $dh ) {
next if /^\./;
my $file = catfile( $root, $_ );
next unless -f $file;
push @file_data, {
path => $file,
size => -s $file,
id => sha256_hex( $file ),
};
}
}
print Dumper \@file_data;
Upvotes: 2
Reputation: 984
Thanks to Wumpus Q. Wumbley's push
suggestion, I have solved my problem:
my @array;
opendir DIR, $dir or die "cannot open dir $dir: $!";
while(my $file = readdir DIR) {
next unless(-f "${\File::Spec->catfile($dir, $file)}");
next if("$file" =~ m/^\./);
#print "${\File::Spec->rel2abs($file)}\n";
my %hash = (
path => File::Spec->rel2abs($file),
size => -s $file,
id => sha256_hex($file),
);
push(@array, \%hash);
#print Dumper sort \@array;
}
closedir DIR;
print Dumper \@array;
I create the "frame" for the hash, and then pass it to the array via reference and the push
function.
Upvotes: 2
Reputation: 691
You have all the code, you are creating an array with the first element. Your way to dereference that hints at an easy way to add others:
my $i = 0;
while(my $file = readdir DIR) {
next unless(-f "${\File::Spec->catfile($dir, $file)}");
next if("$file" =~ m/^\./);
print "${\File::Spec->rel2abs($file)}\n";
$fileref[$i]{path} = File::Spec->rel2abs($file);
$fileref[$i]{size} = -s $fileref[0]{path};
$fileref[$i]{id} = sha256_hex(fileref[0]{path});
$i++;
}
Upvotes: 0