Reputation: 71
I am currently trying to get the sizes of all the files in a directory listing (ignoring any sub-directories). I am using the opendir
and readdir
operations, and for each file I output the name and the size into a file. The File name is correctly output but not the size. I have tried this using the -s
operator and the stat built-in function but with both I get the warning that the value is uninitialized.
My code is:
#!/usr/bin/perl
use strict;
use warnings;
my $dir = $ARGV[0];
opendir(DIR, $dir) or die "Could not open directory '$dir' $!";
my $filename = 'FileSize.txt';
open(my $fh, '>', $filename) or die "Could not open file '$filename' $!";
while (my $file = readdir(DIR)) {
# Ignore Sub-Directories
next unless (-f "$dir/$file");
my $size = -s $file;
print $fh "$file"," ","$size\n";
}
closedir(DIR);
exit 0;
I run the command from within the top level directory itself, including the name of the Sub-directory to be scanned, and get the following error, one for every file in the sub-directory that is processed
C:\Users\lafarnum\Documents>perl FileComp.pl DiskImage
Use of uninitialized value $size in concatenation (.) or string at
FileComp.pl line 18.
Consequently, the file names are correctly output to the output file, but not the file sizes. The output file looks like this
BuildState.txt
data1.cab
data1.hdr
data2.cab
ISSetup.dll
layout.bin
README.doc
setup.bmp
setup.exe
setup.ini
setup.inx
setup.iss
vcredist_x86.exe
_Setup.dll
I think this has something to do with the way I am retrieving the file variable from readdir
. All the examples of using the -s
operator and the stat built-in function have been when users had hard coded the names of the files, not fetched them using readdir
. I am new to using Perl, so apologies if I am making a basic error.
Upvotes: 1
Views: 326
Reputation: 9231
(as pointed out by @tinita) The file test operators require a relative or absolute path to the file, while readdir will return only the basename of the file, so you need to concatenate the directory you're iterating with the basename to get the file path.
my $size = -s "$dir/$file";
For fun, here's how this script might look using Path::Tiny:
use strict;
use warnings;
use Path::Tiny;
my $dir = $ARGV[0];
my $fh = path('FileSize.txt')->openw;
foreach my $file (grep { -f } path($dir)->children) {
my $basename = $file->basename;
my $size = -s $file;
print $fh "$basename $size\n";
}
Upvotes: 2
Reputation: 8811
Something like the below one liner would work..
/usr/libexec> \ls -1 | perl -ne ' while (<>) {chop($_); $size= -s "$_"; print "$size, $_\n" if not -d $_ } '
96168, gam_server
18808, gnupg-pcsc-wrapper
52232, gpg2keys_curl
61120, gpg2keys_finger
60888, gpg2keys_hkp
66432, gpg2keys_ldap
100344, gpg-check-pattern
85616, gpg-preset-passphrase
210416, gpg-protect-tool
21096, hald-addon-acpi
22352, hald-addon-generic-backlight
24136, hald-addon-hid-ups
17328, hald-addon-imac-backlight
31448, hald-addon-input
22776, hald-addon-ipw-killswitch
26224, hald-addon-leds
22384, hald-addon-macbook-backlight
22672, hald-addon-macbookpro-backlight
Upvotes: 0