Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

-s file test operator only works in same directory

by Bowlslaw (Acolyte)
on Dec 08, 2017 at 02:01 UTC ( [id://1205139]=perlquestion: print w/replies, xml ) Need Help??

Bowlslaw has asked for the wisdom of the Perl Monks concerning the following question:

Hello, I have made a perl script which takes the files from a directory listed on the command line and places them into an array of hashes with key/value pairs path:full path to file, size:size of file in bytes, and id:sha256sum of file. It works fine when I use its own directory, but it returns "undef" on the id value when used in other directories, and the $! error is "no such directory or file found", which I find quite odd considering that it lists the filenames sha256sums just fine.
use strict; use warnings; use Data::Dumper qw(Dumper); use File::Spec; use Digest::SHA qw(sha256_hex); print join("\n", @ARGV),"\n\n"; #print Dumper \@ARGV; my $dir = $ARGV[0]; my $url = $ARGV[1]; 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); } closedir DIR; print Dumper sort \@array;

Replies are listed 'Best First'.
Re: -s file test operator only works in same directory
by NetWallah (Canon) on Dec 08, 2017 at 02:12 UTC
    $file contains the relative path (No directory name).

    Early in your loop, you should probably update that to the full path :

    $file = File::Spec->catfile($dir, $file);
    ALso - Why are you using the strange "${\File::Spec...}" syntax ?

                    All power corrupts, but we need electricity.

      Because subrefs are cool?
        That is not a subref.
        perl -E ' say ${\"FFF"}' FFF
        All you are doing is referencing then de-referencing the returned value of the sub.

        It is just a way to call a sub inside quotes - but I dislike the obfuscation it causes.

                        All power corrupts, but we need electricity.

Re: -s file test operator only works in same directory
by Dallaylaen (Chaplain) on Dec 08, 2017 at 07:54 UTC
    You are calling -f on full file name, yet -s on just the base name, hence the discrepancy. I would just cache the full name once and for all (well, until next loop iteration). Something like this:
    while(my $file = readdir DIR) { next if $file =~ /^./; # still working with name only $file = File::Spec->catfile( $dir, $file ); next unless -f $file; # working with full path from now on # ....... proceed with the rest of loop };
Re: -s file test operator only works in same directory
by dbuckhal (Chaplain) on Dec 08, 2017 at 03:22 UTC

    One thing that has helped me in similar situations was to change into the directory containing the files of interest. For example, note the tiny changes to your code:

    use strict; use warnings; use Data::Dumper qw(Dumper); use File::Spec; use Digest::SHA qw(sha256_hex); print join("\n", @ARGV),"\n\n"; #print Dumper \@ARGV; my $dir = $ARGV[0]; my $url = $ARGV[1]; my @array; opendir DIR, $dir or die "cannot open dir $dir: $!"; chdir $dir; # added chdir while(my $file = readdir DIR) { next unless -f $file; # simplified fil +e check next if($file =~ m/^\./); # removed quotes print "${\File::Spec->rel2abs($file)}\n"; my %hash = ( path => File::Spec->rel2abs($file), size => -s $file, id => sha256_hex($file), ); push(@array, \%hash); } closedir DIR; print Dumper sort \@array;

    Hope it works out for you!

    --Derrick

Re: -s file test operator only works in same directory
by hippo (Bishop) on Dec 08, 2017 at 09:16 UTC

    Here is the simple refutation of that assertion.

    use strict; use warnings; use Cwd; use Test::More tests => 2; isnt (getcwd, '/etc', 'Not in /etc/'); cmp_ok (-s '/etc/fstab', '>', 0, '-s /etc/fstab is positive');

    The reason is that given by my speedier brethren: namely absolute versus relative paths.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1205139]
Approved by Athanasius
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others exploiting the Monastery: (9)
As of 2024-04-18 11:05 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found