using File::Find

U

Uno

I just installed perldoc on my machine and wanted to go take a look at
it, to see where it is and what it looks like. For example, I wrote:

$ whereis perlretut
perlretut: /usr/share/man/man1/perlretut.1.gz
$

and poked around there, but I didn't see a perlretut that looked
uncompressed, and it could be there, but this is one of those
directories where if you just hit ls, you get a deluge of files.

So I thought I'd give it a shot with perl and looked at 9.7 of _Perl
Cookbook_, p. 361. I tried to adapt it to the situation and am not
quite sure what I'm looking at:

$ perl find1.pl
Use of uninitialized value in numeric gt (>) at find1.pl line 7.
Use of uninitialized value in numeric gt (>) at find1.pl line 7.
Use of uninitialized value in numeric gt (>) at find1.pl line 7.
/usr/share/man/man1 Tue Mar 22 17:08:00 2011
$ cat find1.pl
#! usr/bin/perl -w
use strict;
use File::Find;
@ARGV = ('/usr/share/man/man1') unless @ARGV;
my ($age, $name);
sub youngest {
return if defined $age && $age > -M;
$age = (stat(_))[9];
$name = $File::Find::name;
}
find(\&youngest, @ARGV);
print "$name " . scalar(localtime($age)) . "\n";
$

It seems to me that $name should be giving me the name of a file in the
directory, not the directory itself. It also seems to me unlikely that
this directory would be born today, and later than its contents.

So 2 questions.
q1) How do I re-write this so that it outputs the filename?
q2) I seem to get a varying number of warnings on "use of uninitialized
value" depending on the directory it runs in. What does it mean?

Thanks for your comment,
and cheers,
 
R

Randal L. Schwartz

Uno> I just installed perldoc on my machine and wanted to go take a look
Uno> at it, to
Uno> see where it is and what it looks like. For example, I wrote:

Uno> $ whereis perlretut
Uno> perlretut: /usr/share/man/man1/perlretut.1.gz
Uno> $

Uno> and poked around there, but I didn't see a perlretut that looked uncompressed,
Uno> and it could be there, but this is one of those directories where if you just
Uno> hit ls, you get a deluge of files.

"man perlretut" would have shown it just fine.

Deleted the rest.
 
U

Uno

Uno> I just installed perldoc on my machine and wanted to go take a look
Uno> at it, to
Uno> see where it is and what it looks like. For example, I wrote:

Uno> $ whereis perlretut
Uno> perlretut: /usr/share/man/man1/perlretut.1.gz
Uno> $

Uno> and poked around there, but I didn't see a perlretut that looked uncompressed,
Uno> and it could be there, but this is one of those directories where if you just
Uno> hit ls, you get a deluge of files.

"man perlretut" would have shown it just fine.

Deleted the rest.

Did you notice that the subject is using File::Find?
 
R

Randal L. Schwartz

Uno> Did you notice that the subject is using File::Find?

"man File::Find" then.
 
R

Randal L. Schwartz

Jürgen> Didn't you mean
Jürgen> perldoc File::Find
Jürgen> maybe?

Oh, sorry. I have tools that make it so that "man File::Find" works.

Much simpler for my brain.
 
U

Uno

perldoc will tell you where the docs are if you ask it to...

perldoc perldoc

NAME
perldoc - Look up Perl documentation in Pod format.

Ok.
perldoc -l perlretut

=head2 Acknowledgments

The inspiration for the stop codon DNA example came from the ZIP
code example in chapter 7 of I<Mastering Regular Expressions>.

The author would like to thank Jeff Pinyan, Andrew Johnson, Peter
Haworth, Ronald J Kimball, and Joe Smith for all their helpful
comments.

=cut

$ /usr/share/perl/5.10/pod/perlretut.pod
bash: /usr/share/perl/5.10/pod/perlretut.pod: Permission denied
$ man cat
$ perldoc -l perlretut
/usr/share/perl/5.10/pod/perlretut.pod
$ cat /usr/share/perl/5.10/pod/perlretut.pod >text1
$ ls
ch09.code find1.pl lst rmtree1 symirror uvi
fdirs find2.pl rename rmtree2 text1
$ whereis perlretut
perlretut: /usr/share/man/man1/perlretut.1.gz
$

Am I correct to think that whereis didn't find the pod file because it
didn't exist when it booted?
 
U

Uno

Jürgen> Didn't you mean
Jürgen> perldoc File::Find
Jürgen> maybe?

Oh, sorry. I have tools that make it so that "man File::Find" works.

Much simpler for my brain.

Does your perl documentation survive the latest install? Although I'm
not a detached observer, I would say that mine did not.
 
A

Alan Curry

I just installed perldoc on my machine and wanted to go take a look at

I'm going to ignore the weird leaps of logic that allowed you to make the
journey from from "I just installed perldoc" to the attempt to write a script
to find the newest installed man page. The script itself is interesting
enough to comment on.
$ perl find1.pl
Use of uninitialized value in numeric gt (>) at find1.pl line 7.
Use of uninitialized value in numeric gt (>) at find1.pl line 7.
Use of uninitialized value in numeric gt (>) at find1.pl line 7.
/usr/share/man/man1 Tue Mar 22 17:08:00 2011
$ cat find1.pl
#! usr/bin/perl -w
use strict;
use File::Find;
@ARGV = ('/usr/share/man/man1') unless @ARGV;
my ($age, $name);
sub youngest {
return if defined $age && $age > -M;
$age = (stat(_))[9];
$name = $File::Find::name;
}
find(\&youngest, @ARGV);
print "$name " . scalar(localtime($age)) . "\n";
$

The most interesting bug in the script is that you're comparing a value
returned by -M to a value (in $age) that came from (stat(_))[9]. Those are
both modification times, but one of them measured in seconds, counting
forward from 1970, and the other one is measured in days, counting backward
from the time the script started running. Pick one of those and use it
consistently. (I'd pick stat. -M is just too weird for anything but golfing)

The next bug is hinted at by the uninitialized value warnings. Since you've
tested $age for definedness before comparing, the only thing that can be
causing the warning is that -M is returning undef. You must have some
dangling symlinks in that directory. To make your script handle dangling
symlinks correctly, you could use (lstat)[9] or you could check for the undef
timestamp and just skip them. Depends on how you want to handle symlinks in
general. File::Find has some options related to symlink following that you
might want to enable.
It seems to me that $name should be giving me the name of a file in the
directory, not the directory itself. It also seems to me unlikely that
this directory would be born today, and later than its contents.

Wow, the densely packed misconceptions! First of all, in File::Find, just as
in find(1), the "directory itself" is a legitimate part of the search output.
There's no reason why "/usr/share/man/man1" can't be the answer to "what is
the youngest file found under /usr/share/man/man1?"... Directories are files
too. If you want to exclude them, put "return if -d" at the top of your
filter function.

Secondly, -M and (stat)[9] are modification times, not birth times. It's
easily possible for a directory to be newer than any file inside it, since a
directory is modified whenever a file is added to the directory or removed
from it.

The time the directory was "born" would not be recorded in a traditional unix
filesystem. Recently some unix filesystems have been created which do record
"birthtime", but since they were not around when perl was invented, perl
doesn't have an easy way of accessing those timestamps. (None that I can find
anyway - looking under -X and stat in perlfunc(1) and also at File::stat(3) I
don't see any mention of birthtime)

If birthtime of the files is what you're after, you'll probably find
modification time to be a poor substitute. I have an installed man page with
a modification time of 15:51:31, December 10, 1992, several times older than
the computer I'm using. Imagine the path that file has taken to get to me! It
must have been compressed and uncompressed with algorithms no longer used,
passed around from FTP mirror to FTP mirror on OSes no longer remembered,
copied from hard drive to tape, CD, and DVD and back a few times, put into
tarballs and other containers and taken back out again, and through all that
it was never modified.

The point of that story is: mtime applies to file contents, not file
location. The mtime of an installed man page is likely to be the time that
it was last modified by the author, not the timestamp of installation on your
machine.

In cases like that, ctime can be a better substitute, as long as you don't do
a lot of chmod'ing of things after they're installed.

Oh and just use ls -ltr next time.
 
P

Peter J. Holzer

I just installed perldoc on my machine and wanted to go take a look at
it, to see where it is and what it looks like. For example, I wrote:

$ whereis perlretut
perlretut: /usr/share/man/man1/perlretut.1.gz
$

Whereis looks only in a few directories. You may want to use find or
locate instead.

[...]
$ perl find1.pl
Use of uninitialized value in numeric gt (>) at find1.pl line 7.
Use of uninitialized value in numeric gt (>) at find1.pl line 7.
Use of uninitialized value in numeric gt (>) at find1.pl line 7.
/usr/share/man/man1 Tue Mar 22 17:08:00 2011
$ cat find1.pl
#! usr/bin/perl -w
use strict;
use File::Find;
@ARGV = ('/usr/share/man/man1') unless @ARGV;
my ($age, $name);
sub youngest {
return if defined $age && $age > -M;
$age = (stat(_))[9];

This is confused: (stat(_))[9] returns a timestamp (expressed in seconds
since the epoch), not an age. -M returns the age in days. You cannot
meaningfully compare them. Since the timestamp of any file is likely to
be much greater than the age of any file of the system you will always
get the name and mtime of the first file (i.e. the directory you
specified).
$name = $File::Find::name;
}
find(\&youngest, @ARGV);
print "$name " . scalar(localtime($age)) . "\n";
$

It seems to me that $name should be giving me the name of a file in the
directory, not the directory itself. It also seems to me unlikely that
this directory would be born today, and later than its contents.

It wasn't "born" today, but it was last modified today. You just
installed a package, didn't you? The package presumably contained a
manpage. The last modified date of the manpage is almost certainly older
than the directory. So the output is probably correct even if the script
is not.
So 2 questions.
q1) How do I re-write this so that it outputs the filename?

Which filename?
q2) I seem to get a varying number of warnings on "use of uninitialized
value" depending on the directory it runs in. What does it mean?

Line 7 is this one:
return if defined $age && $age > -M;

Now where could an "uninitialized value in numeric gt (>)" in this line
occur? There is only one > in this line, so it can only be $age or -M.
It can't be $age because you test whether that's defined. So it can only
be the return value of -M. Now check the docs to find out when -M can
return undef.

hp
 
J

Jürgen Exner

Uno said:
Does your perl documentation survive the latest install? Although I'm
not a detached observer, I would say that mine did not.

???
Would you mind explaining what you are rambling about? It's the second
or third time that you are making some claim about perl documentation
and some installation of something. INSTALLATION OF WHAT?
If by chance you are talking about installation of a new Perl version
(you didn't say!!!) then it depends. If I deleted the old Perl version,
then of course the old documentation is gone, too, just as it should be.
If I didn't delete the old Perl version, then of course the old
documentation is still available, too. In either case, the new version
of Perl automatically comes with its new *matching* version of the docs
anyway. And that's the one you want to use. So what's the point in
babbling about survival of the [old] Perl documentation?

jue
 
U

Uno

Whereis looks only in a few directories. You may want to use find or
locate instead.

$ find /usr/ -name 'perlretut.*'
/usr/share/perl/5.10.1/pod/perlretut.pod
/usr/share/man/man1/perlretut.1.gz
$

Ok.
This is an erratum in the source listing. I don't want to bark too
loudly about it, since I'm grateful that there is a source listing at
all to be occasionally wrong. The text has the following:

$ cat find2.pl
#! usr/bin/perl -w
use strict;
use File::Find;
@ARGV = (".") unless @ARGV;
my ($age, $name);
sub youngest {
return if defined $age && $age > (stat(_))[9];
$age = (stat(_))[9];
$name = $File::Find::name;
}
find(\&youngest, @ARGV);
print "$name " . scalar(localtime($age)) . "\n";
$

This still doesn't solve the problems with this script, one of which is
that I don't really understand the control. It doesn't give the answer
I'm looking for, so I'm gonna scrap it:

$ perl find2.pl
../text1 Wed Mar 23 20:42:43 2011
$ ls -lst
total 168
4 -rw-r--r-- 1 dan dan 291 2011-03-23 20:42 find2.pl
120 -rw-r--r-- 1 dan dan 115005 2011-03-22 21:31 text1
4 -rwxr-xr-x 1 dan dan 299 2011-03-22 17:56 find1.pl
4 -rwxrwxr-x 1 dan dan 278 1998-08-26 14:09 uvi
4 -rwxrwxr-x 1 dan dan 1198 1998-08-26 14:06 symirror
4 -rwxrwxr-x 1 dan dan 170 1998-08-26 14:05 rmtree2
4 -rwxrwxr-x 1 dan dan 420 1998-08-26 14:05 rmtree1
4 -rwxrwxr-x 1 dan dan 243 1998-08-26 14:05 rename
4 -rwxrwxr-x 1 dan dan 2597 1998-08-26 14:05 lst
4 -rwxrwxr-x 1 dan dan 194 1998-08-26 13:02 fdirs
12 -rw-r--r-- 1 dan dan 8884 1998-08-26 13:01 ch09.code
$ ls -ld
drwxrwxr-x 2 dan dan 4096 2011-03-23 20:42 .


The "correct" answer to my eye is ./find2.pl.
It wasn't "born" today, but it was last modified today. You just
installed a package, didn't you? The package presumably contained a
manpage. The last modified date of the manpage is almost certainly older
than the directory. So the output is probably correct even if the script
is not.


Which filename?

Of the file that is the youngest in a given directory besides the
directory itself.
Line 7 is this one:


Now where could an "uninitialized value in numeric gt (>)" in this line
occur? There is only one> in this line, so it can only be $age or -M.
It can't be $age because you test whether that's defined. So it can only
be the return value of -M. Now check the docs to find out when -M can
return undef.

I'm still surprised that a google search for -M turned up nothing, but
I'm gonna go a different direction here with the lst program that
appears in the same chapter, that is already a program listing and
presumably better-polished than whatever appears above:

$ perl lst
..
../find2.pl
../text1
../find1.pl
../uvi
../symirror
../rmtree2
../rmtree1
../rename
../lst
../fdirs
../ch09.code
$ cat lst
#!/usr/bin/perl
# lst - list sorted directory contents (depth first)

use Getopt::Std;
use File::Find;
use File::stat;
use User::pwent;
use User::grent;

getopts('lusrcmi') or die <<DEATH;
Usage: $0 [-mucsril] [dirs ...]
or $0 -i [-mucsrl] < filelist

Input format:
-i read pathnames from stdin
Output format:
-l long listing
Sort on:
-m use mtime (modify time) [DEFAULT]
-u use atime (access time)
-c use ctime (inode change time)
-s use size for sorting
Ordering:
-r reverse sort
NB: You may only use select one sorting option at a time.
DEATH

unless ($opt_i || @ARGV) { @ARGV = ('.') }

if ($opt_c + $opt_u + $opt_s + $opt_m > 1) {
die "can only sort on one time or size";
}

$IDX = 'mtime';
$IDX = 'atime' if $opt_u;
$IDX = 'ctime' if $opt_c;
$IDX = 'size' if $opt_s;

$TIME_IDX = $opt_s ? 'mtime' : $IDX;

*name = *File::Find::name; # forcibly import that variable

# the $opt_i flag tricks wanted into taking
# its filenames from ARGV instead of being
# called from find.

if ($opt_i) {
*name = *_; # $name now alias for $_
while (<>) { chomp; &wanted; } # ok, not stdin really
} else {
find(\&wanted, @ARGV);
}

# sort the files by their cached times, youngest first
@skeys = sort { $time{$b} <=> $time{$a} } keys %time;

# but flip the order if -r was supplied on command line
@skeys = reverse @skeys if $opt_r;

for (@skeys) {
unless ($opt_l) { # emulate ls -l, except for permissions
print "$_\n";
next;
}
$now = localtime $stat{$_}->$TIME_IDX();
printf "%6d %04o %6d %8s %8s %8d %s %s\n",
$stat{$_}->ino(),
$stat{$_}->mode() & 07777,
$stat{$_}->nlink(),
user($stat{$_}->uid()),
group($stat{$_}->gid()),
$stat{$_}->size(),
$now, $_;
}

# get stat info on the file, saving the desired
# sort criterion (mtime, atime, ctime, or size)
# in the %time hash indexed by filename.
# if they want a long list, we have to save the
# entire stat object in %stat. yes, this is a
# hash of objects
sub wanted {
my $sb = stat($_); # XXX: should be stat or lstat?
return unless $sb;
$time{$name} = $sb->$IDX(); # indirect method call
$stat{$name} = $sb if $opt_l;
}

# cache user number to name conversions
sub user {
my $uid = shift;
$user{$uid} = getpwuid($uid)->name || "#$uid"
unless defined $user{$uid};
return $user{$uid};
}

# cache group number to name conversions
sub group {
my $gid = shift;
$group{$gid} = getgrgid($gid)->name || "#$gid"
unless defined $group{$gid};
return $group{$gid};
}
$
 
U

Uno

$ perl find1.pl
Use of uninitialized value in numeric gt (>) at find1.pl line 7.
Use of uninitialized value in numeric gt (>) at find1.pl line 7.
Use of uninitialized value in numeric gt (>) at find1.pl line 7.
/usr/share/man/man1 Tue Mar 22 17:08:00 2011
$ cat find1.pl
#! usr/bin/perl -w
use strict;
use File::Find;
@ARGV = ('/usr/share/man/man1') unless @ARGV;
my ($age, $name);
sub youngest {
return if defined $age&& $age> -M;
$age = (stat(_))[9];
$name = $File::Find::name;
}
find(\&youngest, @ARGV);
print "$name " . scalar(localtime($age)) . "\n";
$

The most interesting bug in the script is that you're comparing a value
returned by -M to a value (in $age) that came from (stat(_))[9]. Those are
both modification times, but one of them measured in seconds, counting
forward from 1970, and the other one is measured in days, counting backward
from the time the script started running. Pick one of those and use it
consistently. (I'd pick stat. -M is just too weird for anything but golfing)

Sorry about that Alan, that seems to have a been a typo, and if that's
the way it's been going for you out on the links, then I'm sorry for
your golf game too. I'm breaking my frisbee game down completely this
season, so far with 0 success except no elbow injury.
The next bug is hinted at by the uninitialized value warnings. Since you've
tested $age for definedness before comparing, the only thing that can be
causing the warning is that -M is returning undef. You must have some
dangling symlinks in that directory. To make your script handle dangling
symlinks correctly, you could use (lstat)[9] or you could check for the undef
timestamp and just skip them. Depends on how you want to handle symlinks in
general. File::Find has some options related to symlink following that you
might want to enable.

dangling_symlinks

If true and a code reference, will be called with the symbolic link
name and the directory it lives in as arguments. Otherwise, if true and
warnings are on, warning "symbolic_link_name is a dangling symbolic
link\n" will be issued. If false, the dangling symbolic link will be
silently ignored.
Wow, the densely packed misconceptions! First of all, in File::Find, just as
in find(1), the "directory itself" is a legitimate part of the search output.
There's no reason why "/usr/share/man/man1" can't be the answer to "what is
the youngest file found under /usr/share/man/man1?"... Directories are files
too. If you want to exclude them, put "return if -d" at the top of your
filter function.

I can pack them in can't I? I'm very confused still:
$ cat find2.pl
#! usr/bin/perl -w
use strict;
use File::Find;
@ARGV = (".") unless @ARGV;
my ($age, $name);
sub youngest {
return if -d;
$age = (stat(_))[9];
$name = $File::Find::name;
}
find(\&youngest, @ARGV);
print "$name " . scalar(localtime($age)) . "\n";
$ ls -t
find2.pl text1 uvi rmtree2 rename fdirs
lst2 find1.pl symirror rmtree1 lst ch09.code
$ perl find2.pl
../text1 Wed Mar 23 22:05:26 2011
$

To my eye, the "right" answer is find2.pl. Is there something about a
file not being able to see itself?
Secondly, -M and (stat)[9] are modification times, not birth times. It's
easily possible for a directory to be newer than any file inside it, since a
directory is modified whenever a file is added to the directory or removed
from it.

I see.
The time the directory was "born" would not be recorded in a traditional unix
filesystem. Recently some unix filesystems have been created which do record
"birthtime", but since they were not around when perl was invented, perl
doesn't have an easy way of accessing those timestamps. (None that I can find
anyway - looking under -X and stat in perlfunc(1) and also at File::stat(3) I
don't see any mention of birthtime)

If birthtime of the files is what you're after, you'll probably find
modification time to be a poor substitute. I have an installed man page with
a modification time of 15:51:31, December 10, 1992, several times older than
the computer I'm using. Imagine the path that file has taken to get to me! It
must have been compressed and uncompressed with algorithms no longer used,
passed around from FTP mirror to FTP mirror on OSes no longer remembered,
copied from hard drive to tape, CD, and DVD and back a few times, put into
tarballs and other containers and taken back out again, and through all that
it was never modified.

The point of that story is: mtime applies to file contents, not file
location. The mtime of an installed man page is likely to be the time that
it was last modified by the author, not the timestamp of installation on your
machine.
Gotcha.

In cases like that, ctime can be a better substitute, as long as you don't do
a lot of chmod'ing of things after they're installed.

Oh and just use ls -ltr next time.

Thanks, Alan, that helps for sure. I've been looking at some of the
issues he talked about in light of the lst program in chp. 9.13 of _Perl
Cookbook_.

$ perl lst -l /usr/share/man >text2

These are the oldest files there:

1000886 0644 1 root root 6096 Wed Oct 10 09:25:04 2007
/usr/share/man/man1/readom.1.gz
1000250 0644 1 root root 3460 Wed Nov 22 09:56:03 2006
/usr/share/man/man3/IO::String.3pm.gz
1004123 0644 1 root root 562 Tue Oct 26 10:33:49 2004
/usr/share/man/man8/install-sgmlcatalog.8.gz
1004444 0644 1 root root 704 Tue Oct 26 10:33:49 2004
/usr/share/man/man8/update-catalog.8.gz
1002021 0644 1 root root 4013 Wed Jul 28 14:36:05 2004
/usr/share/man/man3/Tie::IxHash.3pm.gz


The directories are the newest:

999454 0755 2 root root 61440 Tue Mar 22 17:08:00 2011
/usr/share/man/man1
999456 0755 2 root root 110592 Tue Mar 22 17:08:00 2011
/usr/share/man/man3
999461 0755 2 root root 28672 Sat Mar 12 17:09:52 2011
/usr/share/man/man8
999460 0755 2 root root 12288 Fri Mar 11 17:44:05 2011
/usr/share/man/man7
999457 0755 2 root root 4096 Fri Mar 11 17:44:03 2011
/usr/share/man/man4
999458 0755 2 root root 12288 Fri Mar 11 17:43:57 2011
/usr/share/man/man5
999653 0755 2 root root 4096 Fri Mar 11 17:42:57 2011
/usr/share/man/fr/man8
1001029 0644 1 root root 1053 Fri Mar 4 14:01:19 2011
/usr/share/man/man1/avahi-publish-service.1.gz

, and it seems correct that ./man1 would be the youngest directory since
it has the youngest file (not including the directory, which is itself a
file).

The listing for the author's lst is on my response to Peter, so I won't
repeat that. What I continue to have trouble with is "breaking into"
perl controls. The more idiomatic the perl is, the less I can see how
control goes:

$ perl lst2
../text2
..
../find2.pl
../lst2
../text1
../find1.pl
../uvi
../symirror
../rmtree2
../rmtree1
../rename
../lst
../fdirs
../ch09.code
$ cat lst2
#!/usr/bin/perl
# lst - list sorted directory contents (depth first)

use Getopt::Std;
use File::Find;
use File::stat;
use User::pwent;
use User::grent;

getopts('lusrcmi') or die <<DEATH;
Usage: $0 [-mucsril] [dirs ...]
or $0 -i [-mucsrl] < filelist

Input format:
-i read pathnames from stdin
Output format:
-l long listing
Sort on:
-m use mtime (modify time) [DEFAULT]
-u use atime (access time)
-c use ctime (inode change time)
-s use size for sorting
Ordering:
-r reverse sort
NB: You may only use select one sorting option at a time.
DEATH

unless ($opt_i || @ARGV) { @ARGV = ('.') }

if ($opt_c + $opt_u + $opt_s + $opt_m > 1) {
die "can only sort on one time or size";
}

$IDX = 'mtime';
$IDX = 'atime' if $opt_u;
$IDX = 'ctime' if $opt_c;
$IDX = 'size' if $opt_s;

$TIME_IDX = $opt_s ? 'mtime' : $IDX;

*name = *File::Find::name; # forcibly import that variable

# the $opt_i flag tricks wanted into taking
# its filenames from ARGV instead of being
# called from find.

if ($opt_i) {
*name = *_; # $name now alias for $_
while (<>) { chomp; &wanted; } # ok, not stdin really
} else {
find(\&wanted, @ARGV);
}

# sort the files by their cached times, youngest first
@skeys = sort { $time{$b} <=> $time{$a} } keys %time;

# but flip the order if -r was supplied on command line
@skeys = reverse @skeys if $opt_r;

my $counter = 0;
for (@skeys) {
unless ($opt_l) { # emulate ls -l, except for permissions
print "$_\n";
next;
}
$counter++;
print "counter is $counter\n";
if ($counter eq 1) {
print "$_ is the oldest file in this directory.\n";
}
$now = localtime $stat{$_}->$TIME_IDX();
printf "%6d %04o %6d %8s %8s %8d %s %s\n",
$stat{$_}->ino(),
$stat{$_}->mode() & 07777,
$stat{$_}->nlink(),
user($stat{$_}->uid()),
group($stat{$_}->gid()),
$stat{$_}->size(),
$now, $_;
}

# get stat info on the file, saving the desired
# sort criterion (mtime, atime, ctime, or size)
# in the %time hash indexed by filename.
# if they want a long list, we have to save the
# entire stat object in %stat. yes, this is a
# hash of objects
sub wanted {
my $sb = stat($_); # XXX: should be stat or lstat?
return unless $sb;
$time{$name} = $sb->$IDX(); # indirect method call
$stat{$name} = $sb if $opt_l;
}

# cache user number to name conversions
sub user {
my $uid = shift;
$user{$uid} = getpwuid($uid)->name || "#$uid"
unless defined $user{$uid};
return $user{$uid};
}

# cache group number to name conversions
sub group {
my $gid = shift;
$group{$gid} = getgrgid($gid)->name || "#$gid"
unless defined $group{$gid};
return $group{$gid};
}
$

Simple question: why does this script go off exactly like the original,
that is, why does program never print the value of $counter?
 
U

Uno

Uno said:
Does your perl documentation survive the latest install? Although I'm
not a detached observer, I would say that mine did not.

???
Would you mind explaining what you are rambling about? It's the second
or third time that you are making some claim about perl documentation
and some installation of something. INSTALLATION OF WHAT?
If by chance you are talking about installation of a new Perl version
(you didn't say!!!) then it depends. If I deleted the old Perl version,
then of course the old documentation is gone, too, just as it should be.
If I didn't delete the old Perl version, then of course the old
documentation is still available, too. In either case, the new version
of Perl automatically comes with its new *matching* version of the docs
anyway. And that's the one you want to use. So what's the point in
babbling about survival of the [old] Perl documentation?

I have a lot of misconceptions, as I'm even newer to unix than I am
perl, and I don't mind when you take a tone with me, as you also help as
you castigate. That's not true of everyone on usenet.

I shouldn't have gone on Uri's thread and insulted him, but then he
shouldn't have taken that giant dump on mine.

I was thinking that I could take a look at the subjects of c.l.p.misc
and dug up this:
$ perl jabba6.pl
s4 is Re: using File::Find
FAQ 4.53 How do I manipulate arrays of bits?
Re: File::Slurp 9999.14 is released
Re: using File::Find
FAQ 2.1 What machines support perl? Where do I get it?
Re: File::Slurp 9999.14 is released
Perl script running external command
FAQ 8.38 How do I timeout a slow event?
Re: polling TCP server on Win32 (with Tk)
Re: module for MSCRM?
using File::Find :eR
$ cat jabba6.pl
#!/usr/bin/perl

## jabba6.pl, 2007-10-20

use strict;
use warnings;
use Net::NNTP ();

use constant NUMBER_OF_ARTICLES => 10;
use constant GROUP_NAME => 'comp.lang.perl.misc';
use constant SERVER_NAME => 'News.Individual.NET';
use constant NNTP_DEBUG => 0;

my $nntp = Net::NNTP->new(SERVER_NAME, 'Debug' => NNTP_DEBUG) or die;
my $USER = '';
my $PASS = '';

$nntp->authinfo($USER,$PASS) or die $!;


my($article_count, $first_article, $last_article) =

$nntp->group(GROUP_NAME) or die;


# Which XOVER fields contain Subject: and From:?
my $count = 0;
my %xover_fmt = map( ($_, $count++), @{ $nntp->overview_fmt or die} );
die unless exists $xover_fmt{'Subject:'};
my $subject_offset = $xover_fmt{'Subject:'};
my $from_offset = $xover_fmt{'From:'};

my(@xover, $start_article);
RETRIEVE: while ($#xover+1 < NUMBER_OF_ARTICLES and $last_article >=

$first_article) {

# How many articles do we need? Stop retrieving if we have enough
my $articles_required = NUMBER_OF_ARTICLES - ($#xover+1) or last

RETRIEVE;


# Fetch overview information for the articles
$start_article = $last_article - ($articles_required-1);
$start_article = $start_article > $first_article ? $start_article :

$first_article;

my $xover_query = $start_article == $last_article ?
$start_article :
[$start_article, $last_article];
my $xover_ref = $nntp->xover($xover_query) or die;

# Store headers for the articles we've retrieved
foreach (sort {$b <=> $a} keys %$xover_ref) {
push @xover, $xover_ref->{$_};
}
} continue {
# Move the pointer forward to fetch previous articles
$last_article = $start_article - 1;
}

# Disconnect from the NNTP server
$nntp->quit;

my $s4 = join("\n", map ($_->[$subject_offset],@xover));

print STDOUT " s4 is $s4\n";

my @words = split " ", $s4;

$words[0] = reverse $words[0];


#big finish

print STDOUT " $words[1] $words[2] ";
print STDOUT " $words[0] \n";

__END__


$

That seems to work.
 
P

Peter J. Holzer

#! usr/bin/perl -w
^ There is a / missing here. Please don't retype your scripts, use
cut and paste.
use strict;
use File::Find;
@ARGV = (".") unless @ARGV;
my ($age, $name);
sub youngest {
return if defined $age && $age > (stat(_))[9];

There may be another typo in this line, or (more likely) a logical
error: Read up on the special file descriptor _ and how to use it (or
just don't use it).
$age = (stat(_))[9];

Also, give your variables descriptive names. stat does NOT return an
age. If you rename the variable to what it really is, you will probably
discover the second logical error.
$name = $File::Find::name;
}
find(\&youngest, @ARGV);
print "$name " . scalar(localtime($age)) . "\n";
$

This still doesn't solve the problems with this script,

Of course not. It contains at least two errors.
one of which is that I don't really understand the control.

What control?

Of the file that is the youngest in a given directory besides the
directory itself.

Your script doesn't contain anything whichg corresponds to "besides the
directory itself". You want that you have to program it. Perl can't read
your mind.

I'm still surprised that a google search for -M turned up nothing,

Don't google, read the documentation that comes with perl

perldoc -f -M

(Prefixing a term with "-" excludes that term from the search in Google.
You didn't want to search for all pages except those which contain an
"M", did you?)

hp
 
P

Peter J. Holzer

I can pack them in can't I? I'm very confused still:
$ cat find2.pl
#! usr/bin/perl -w
use strict;
use File::Find;
@ARGV = (".") unless @ARGV;
my ($age, $name);
sub youngest {
return if -d;
$age = (stat(_))[9];
$name = $File::Find::name;
}
find(\&youngest, @ARGV);
print "$name " . scalar(localtime($age)) . "\n";

What part of this script finds the youngest file?

hp
 
U

Uno

U> I have a lot of misconceptions, as I'm even newer to unix than I am
U> perl, and I don't mind when you take a tone with me, as you also help
U> as you castigate. That's not true of everyone on usenet.

so if you have misconceptions, shouldn't you learn the culture before
you go barging in? did you read the posted guidelines here?

Yes, I have.
U> I shouldn't have gone on Uri's thread and insulted him, but then he
U> shouldn't have taken that giant dump on mine.

no i didn't. i posted about my module release. you stupidly dumped on
that and didn't even understand what it was about.

tad plonked you. i read your posts now to get a laugh.

Well I look forward to us spending more quality time with each other.


cpan[1]> install CPAN: Storable loaded ok (v2.20)
Going to read '/home/dan/.cpan/Metadata'
Database was generated on Wed, 23 Mar 2011 17:27:15 GMT
Running install for module 'CPAN: Data::Dumper loaded ok (v2.124)
'YAML' not installed, falling back to Data::Dumper and Storable to read
prefs '/home/dan/.cpan/prefs'
Running make for R/RV/RVA/NNTPClient-0.37.tar.gz
CPAN: Digest::SHA loaded ok (v5.47)
CPAN: Compress::Zlib loaded ok (v2.02)
Checksum for
/home/dan/.cpan/sources/authors/id/R/RV/RVA/NNTPClient-0.37.tar.gz ok
Scanning cache /home/dan/.cpan/build for sizes
.............................................................................DONE
CPAN: Archive::Tar loaded ok (v1.52)
NNTPClient-0.37/
NNTPClient-0.37/Makefile.PL
NNTPClient-0.37/demos/
NNTPClient-0.37/demos/NNTPFetchProgress.pm
NNTPClient-0.37/demos/NNTPHuge.pm
NNTPClient-0.37/test.pl
NNTPClient-0.37/NNTPClient.pm
NNTPClient-0.37/README
NNTPClient-0.37/MANIFEST
CPAN: File::Temp loaded ok (v0.22)

CPAN.pm: Going to build R/RV/RVA/NNTPClient-0.37.tar.gz

Checking if your kit is complete...
Looks good
Writing Makefile for cp NNTPClient.pm blib/lib/News/NNTPClient.pm
Manifying blib/man3/RVA/NNTPClient-0.37.tar.gz
make -- OK
Warning (usually harmless): 'YAML' not installed, will not store
persistent state
Running make test
PERL_DL_NONLAZY=1 /usr/bin/perl "-Iblib/lib" "-Iblib/arch" test.pl
1..37
ok 1

These tests are as much a test of your news server as they are a
test of Not all of these tests will pass.

The following tests rely on the existence of an available news
server. If the environment variable NNTPSERVER is not set, then
"news" will be used. If you don't have access to a news server,
ok(), okprint(), code(), and postok() will fail. postok() will
also fail if you don't have permission to post.

Bad hostname: news at test.pl line 36
ok 2 (version)
ok 3 (debug)
ok 4 (eol)
ok 5 (gmt)
ok 6 (fourdigityear)
ok 7 (message)
not ok 8 (code)
not ok 9 (ok)
not ok 10 (okprint)
not ok 11 (postok)
has been closed
at test.pl line 43
not ok 12 (mode_reader)
has been closed
at test.pl line 43
not ok 13 (list)
has been closed
at test.pl line 43
not ok 14 (help)
has been closed
at test.pl line 43
not ok 15 (slave)

In addition to needing access to a news server, the following
tests also rely on the existence and permission to post to the
news group "test".

has been closed
at test.pl line 57
not ok 16 (post)
has been closed
at test.pl line 67
not ok 17 (group)
has been closed
at test.pl line 71
not ok 18 (article)
has been closed
at test.pl line 71
not ok 19 (body)
has been closed
at test.pl line 71
not ok 20 (head)
has been closed
at test.pl line 71
not ok 21 (last)
has been closed
at test.pl line 71
not ok 22 (next)
has been closed
at test.pl line 71
not ok 23 (stat)
has been closed
at test.pl line 79
not ok 24 (newgroups)
has been closed
at test.pl line 79
not ok 25 (newnews)
has been closed
at test.pl line 88
not ok 26 (date)
has been closed
at test.pl line 88
not ok 27 (listgroup)

The following are all "extra" commands that may or may not be
implemented on your server. Those that are not implemented should
show an NNTPERROR: 500

has been closed
at test.pl line 102
not ok 28 (xpath )
has been closed
at test.pl line 106
not ok 29 (xgtitle)
has been closed
at test.pl line 106
not ok 30 (xhdr)
has been closed
at test.pl line 106
not ok 31 (xpat)
has been closed
at test.pl line 106
not ok 32 (xover)
has been closed
at test.pl line 106
not ok 33 (xmotd)
has been closed
at test.pl line 106
not ok 34 (xthread)
has been closed
at test.pl line 106
not ok 35 (xindex)
has been closed
at test.pl line 106
not ok 36 (xsearch)

Remember, just because some tests failed doesn't mean that there
is anything wrong with These tests also depend
on the proper operation and implementation of your news server.
For example, the XPATH command on my server does not seem to work
anymore.

not ok 37 (quit)
RVA/NNTPClient-0.37.tar.gz
make test -- OK
Warning (usually harmless): 'YAML' not installed, will not store
persistent state
Running make install
Prepending /home/dan/.cpan/build/NNTPClient-0.37-8BLF8t/blib/arch
/home/dan/.cpan/build/NNTPClient-0.37-8BLF8t/blib/lib to PERL5LIB for
'install'
Manifying blib/man3/!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ERROR: Can't create '/usr/local/man/man3'
mkdir /usr/local/man/man3: Permission denied at
/usr/share/perl/5.10/ExtUtils/Install.pm line 483

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
at -e line 1
make: *** [pure_site_install] Error 13
RVA/NNTPClient-0.37.tar.gz
make install -- NOT OK
Warning (usually harmless): 'YAML' not installed, will not store
persistent state
Failed during this command:
RVA/NNTPClient-0.37.tar.gz : install NO

cpan[2]> ^CCaught SIGINT, trying to continue
^CGot another SIGINTNo history written (no histfile specified).
Lockfile removed.

$

I seem to have lost more of my perl capability than I had even realized.
I installed yaml but might need to reboot.
 
U

Uri Guttman

U> I have a lot of misconceptions, as I'm even newer to unix than I am
U> perl, and I don't mind when you take a tone with me, as you also help
U> as you castigate. That's not true of everyone on usenet.
U> Yes, I have.

then you didn't comprehend them. you keep breaking the rules in it.U> I shouldn't have gone on Uri's thread and insulted him, but then he
U> shouldn't have taken that giant dump on mine.
U> Well I look forward to us spending more quality time with each other.

not likely. i place perl people in jobs. i would not be helping you get
a job with your attitude.

uri
 
J

Jürgen Exner

Uno said:
Uno said:
On 03/22/2011 09:09 PM, Randal L. Schwartz wrote:

Jürgen> Didn't you mean
Jürgen> perldoc File::Find
Jürgen> maybe?

Oh, sorry. I have tools that make it so that "man File::Find" works.

Does your perl documentation survive the latest install? Although I'm
not a detached observer, I would say that mine did not.

???
Would you mind explaining what you are rambling about? It's the second
or third time that you are making some claim about perl documentation
and some installation of something. INSTALLATION OF WHAT?
If by chance you are talking about installation of a new Perl version
(you didn't say!!!) then it depends. If I deleted the old Perl version,
then of course the old documentation is gone, too, just as it should be.
If I didn't delete the old Perl version, then of course the old
documentation is still available, too. In either case, the new version
of Perl automatically comes with its new *matching* version of the docs
anyway. And that's the one you want to use. So what's the point in
babbling about survival of the [old] Perl documentation?

I have a lot of misconceptions, as I'm even newer to unix than I am
perl,

That's ok. Everyone started somewhere. But please see below.
and I don't mind when you take a tone with me, as you also help as
you castigate. That's not true of everyone on usenet.

Well, thanks. But actually I did mean what I wrote: what do you mean by
"survives a new installation". At least now we know that you were
probably talking about Perl on Unix. But I still do not understand what
you meant by "surviving a new installation".
I shouldn't have gone on Uri's thread and insulted him, but then he
shouldn't have taken that giant dump on mine.

What does this have to do with perl docs surviving an installation?
I was thinking that I could take a look at the subjects of c.l.p.misc
and dug up this:

[list of CLPM subject lines snipped]
What does this have to with "surviving an installation"?

[program snipped]
What does this have to do with "surviving an installation"?

I honestly mean it: I do not understand what you are writing.
I was asking very specifically about what you mean by "surving an
installation". To _THIS_ question you replied with the answers above
(which I partially snipped for brevity). I do not understand how your
reply explains what you meant by "surviving an installation".
Maybe it is me and I am just too stupid, but I don't see how your answer
relates to my request for explanation.
If "surviving an installation" is no longer a topic for you then that is
fine. But you replied to my question about, so obviously you were trying
to explain or you wouldn't have replied. just your reply didn't explain
anything. So I am wondering again and scratching my head: what did you
want to tell us with that reply?

jue
 
D

Dave Saville

perldoc will tell you where the docs are if you ask it to...

perldoc perldoc

perldoc -l perlretut

Yeah, *if* you know what you want, what perl calls it, and what
switches perldoc needs to find it. :-( What the perl docs need is the
equivalent of "man -k". perldoc -q does not quite cut it.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,994
Messages
2,570,222
Members
46,809
Latest member
moe77

Latest Threads

Top