[26680] in Perl-Users-Digest
Perl-Users Digest, Issue: 8787 Volume: 10
daemon@ATHENA.MIT.EDU (Perl-Users Digest)
Thu Dec 22 18:05:44 2005
Date: Thu, 22 Dec 2005 15:05:06 -0800 (PST)
From: Perl-Users Digest <Perl-Users-Request@ruby.OCE.ORST.EDU>
To: Perl-Users@ruby.OCE.ORST.EDU (Perl-Users Digest)
Perl-Users Digest Thu, 22 Dec 2005 Volume: 10 Number: 8787
Today's topics:
Concatenating 2 Perl Strings <wh2leung@student.cs.uwaterloo.ca>
Re: Concatenating 2 Perl Strings <no@email.com>
Re: Dynamic directory handles? <whoever@whereever.com>
Re: Dynamic directory handles? <whoever@whereever.com>
Re: Dynamic directory handles? <whoever@whereever.com>
Re: Dynamic directory handles? <xx087@freenet.carleton.ca>
Re: Dynamic directory handles? <tintin@invalid.invalid>
Re: getting info from a bash shell script into perl var <rich@newsguy.com>
Re: line-oriented debugger <Patrick_member@newsguy.com>
Digest Administrivia (Last modified: 6 Apr 01) (Perl-Users-Digest Admin)
----------------------------------------------------------------------
Date: Thu, 22 Dec 2005 17:13:55 -0500
From: William <wh2leung@student.cs.uwaterloo.ca>
Subject: Concatenating 2 Perl Strings
Message-Id: <Pine.GSO.4.64.0512221707280.19617@cpu02.student.cs.uwaterloo.ca>
Expected output:
/local/home/mk_murex/eod/fo_files/Vols/trs_vol.txt_back
Current output:
/local/home/mk_murex/eod/fo_files/Vols/
/local/home/mk_murex/eod/fo_files/Vols/trs_vol.txt_back
Code in question:
#!/usr/bin/perl -w
use strict;
my $InputFileDir = "/local/home/mk_murex/eod/fo_files/Vols/";
my $RunDir = "/mkapp/webapps/mxrt-cgi/upload_vol/";
my $filename = "trs_vol.txt";
my $scriptname = "upload_vol_main.pl";
my $checklist = "dummylist.txt";
my $cmd = $RunDir . $scriptname;
my $extension = "_back";
my $originalList = $InputFileDir . $filename;
my $originalListBack = $originalList . $extension;
my $dummy_list = $RunDir . $checklist;
#print $originalList . "\n";
print $originalListBack . "\n";
# need to rename the original trs_vol.txt
system "mv $originalList $originalListBack";
Questions:
1a) Why is the value in $originalListBack concatenated?
1b) Why is the concatenation only has the value of $InputFileDir and not
$InputFileDir . $filename?
1c) What is the proper way of concatenating a Perl string other than using
"join()"? Right now I am using a lot of variables.
P.S. I checked perldoc -f join
Thanks.
------------------------------
Date: Thu, 22 Dec 2005 22:27:56 +0000
From: Brian Wakem <no@email.com>
Subject: Re: Concatenating 2 Perl Strings
Message-Id: <410njdF1brrr9U1@individual.net>
William wrote:
> Expected output:
> /local/home/mk_murex/eod/fo_files/Vols/trs_vol.txt_back
That's what I get.
> Current output:
> /local/home/mk_murex/eod/fo_files/Vols/
> /local/home/mk_murex/eod/fo_files/Vols/trs_vol.txt_back
I don't get that.
> Code in question:
>
> #!/usr/bin/perl -w
>
> use strict;
>
> my $InputFileDir = "/local/home/mk_murex/eod/fo_files/Vols/";
> my $RunDir = "/mkapp/webapps/mxrt-cgi/upload_vol/";
> my $filename = "trs_vol.txt";
> my $scriptname = "upload_vol_main.pl";
> my $checklist = "dummylist.txt";
> my $cmd = $RunDir . $scriptname;
> my $extension = "_back";
>
> my $originalList = $InputFileDir . $filename;
> my $originalListBack = $originalList . $extension;
> my $dummy_list = $RunDir . $checklist;
>
> #print $originalList . "\n";
> print $originalListBack . "\n";
>
> # need to rename the original trs_vol.txt
> system "mv $originalList $originalListBack";
>
>
> Questions:
Your questions don't seem to apply as the output is what you expected.
--
Brian Wakem
Email: http://homepage.ntlworld.com/b.wakem/myemail.png
------------------------------
Date: Thu, 22 Dec 2005 17:00:59 -0000
From: "IanW" <whoever@whereever.com>
Subject: Re: Dynamic directory handles?
Message-Id: <doem4b$6ie$1@blackmamba.itd.rl.ac.uk>
"A. Sinan Unur" <1usa@llenroc.ude.invalid> wrote in message
news:Xns97344FEAA98EDasu1cornelledu@127.0.0.1...
> First off, you are better off doing this using the File::Find module
> rather than using recursion. If this is not a learning exercise, then I
> would also urge you to look at File::Find::Rule to simplify matters when
> processing items one by one.
>
>> ================
>> #use strict;
>>
>> my $basedir = "j:/files/sw-test";
>
> The program should check @ARGV for an argument, and supply a reasonable
> default if one is not present.
It will actually be a subroutine that forms part of a larger CGI script and
the basedir will actually be passed from a form field.
>> my $fcount = 0;
>> my $fsize = 0;
>> my $dcount = 0;
>
> These are values that should be returned by your sub. You might want to
> check for calling context in the sub and supply an appropriate scalar
> value.
I see the way you've done it in the modified code below, however I didn't
think there was anything wrong with a few global scope vars as long as you
don't forget you've used them globally and then try and use the same names
in another unrelated part of the script... but it's not a huge script and I
can keep track of those things easily enough.
>> dircount();
>>
>> sub dircount {
>> my($cdir) = shift;
>> $cdir .= "/" if $cdir ne "";
>> my $dh = "DH" . length($cdir);
>
> Using lexical dirhandles, this should not be necessary.
lexical is one of those words that I've never got my head round in
programming terms, but I see in the example you've not given $dh a value,
which ties in with what Anno says about opendir creating an anonymous
handle.
>> opendir($dh,"$basedir/$cdir");
>
> You should *always* check if calls to open/opendir succeeded.
Must admit I get a bit lazy in CGI scripts with that, because to be
user-friendly, it means more than just adding "die..." bit to the end of the
open line. I've also never come across a directory or file that wouldn't
open on any of my scripts..
>> while(my $fl = readdir($dh)){
>> next if $fl =~ /^\.{1,2}$/;
>> if(-d "$basedir/$cdir$fl"){
>> $dcount++;
>> dircount("$cdir$fl");
>> }
>
> I do prefer using File::Spec for path manipulation.
>
>> If I "use strict" it says "Can't use string ("DH0") as a symbol ref
>> while "strict refs" in use at D:\test.pl line 14". What's the best way
>> to get round this, since I need a dynamic dir handle for the routine
>> to work properly.
>
> Here is a revised version of your code. I cannot vouch for its accuracy,
> since there seems to be discrepancy between the output of this script
> and that of du on my system (probably because the space taken by zero-
> length files is not taken to account). As always, corrections welcome:
>
> #!/usr/bin/perl
>
> use strict;
> use warnings;
>
> use File::Spec::Functions qw(canonpath catfile);
>
> my $basedir = canonpath($ARGV[0] || '.');
> my ($fcount, $dcount, $fsize) = dircount($basedir);
>
>
> printf("%d files and %d directories totalling %d bytes in size\n",
> $fcount, $dcount, $fsize);
>
> sub dircount {
> my ($cdir) = @_;
> my ($fcount, $dcount, $fsize) = (0, 0, 0);
ahh yes of course :) I was thinking of sth along those lines, though thought
I might have to use qw//
> my $path = catfile($basedir, $cdir);
> opendir my $dh, $path or die "Cannot open directory '$path': $!";
> while (my $fl = readdir($dh)){
> next if $fl eq '.' or $fl eq '..';
is there any reason for doing it that way over my original line using a
regexp? is it a performance thing?
> if(-d (my $d = catfile($path, $fl))){
> $dcount++;
> my ($fc, $dc, $fs) = dircount($d);
> $fcount += $fc;
> $dcount += $dc;
> $fsize += $fs;
Would the following work, a a shortened version of those 3 lines?
($fcount, $dcount, $fsize) += ($fc, $dc, $fs);
> } else {
> $fcount++;
> $fsize += -s $d;
> }
> }
> close($dh);
> return ($fcount, $dcount, $fsize);
> }
thanks :)
Ian
------------------------------
Date: Thu, 22 Dec 2005 17:07:24 -0000
From: "IanW" <whoever@whereever.com>
Subject: Re: Dynamic directory handles?
Message-Id: <doemgd$6mm$1@blackmamba.itd.rl.ac.uk>
> Just leave $dh undefined instead of setting it to a string value.
> opendir() will then create an anonymous directory handle. So change
>
> my $dh = "DH" . length($cdir);
>
> to
>
> my $dh;
I like that solution :)
> Also, you call dircount() without an argument. Presumably you wanted
> to say
>
> dircount( $basedir);
well, $basedir is a global var and I put it in all the places it's needed
anyway
> A better solution would be to use the standard module File::Find:
>
> use File::Find;
>
> sub dircount {
> my $cdir = shift;
> find sub {
> if ( -d ) {
> ++ $dcount;
> } else {
> ++ $fcount;
> $fsize += -s;
> }
> }, $cdir;
> }
that's very concise, thanks! I looked at the File:Find module docs before
but the document made my eyes glaze over. I suppose it's one of those
modules that really useful once you've taken teh time to plow through the
docs and understand it properly.
Regards
Ian
------------------------------
Date: Thu, 22 Dec 2005 17:32:12 -0000
From: "IanW" <whoever@whereever.com>
Subject: Re: Dynamic directory handles?
Message-Id: <doenus$765$1@blackmamba.itd.rl.ac.uk>
"Tad McClellan" <tadmc@augustmail.com> wrote in message
news:slrndqlck1.71n.tadmc@magna.augustmail.com...
> IanW <whoever@whereever.com> wrote:
>
>> I have a chunk of code that counts files.dirs and size for a directory
>> tree.
>
>
> You have a whole bunch of problems, some big, some small.
oh dear.. I was worried that might happen! ;)
> I'll mention the lesser ones in comments about your code below,
> but the 3 big ones are:
>
> 1) You should always enable warnings (and strict) when
> developing Perl code.
>
> 2) You get a dynamic dirhandle the same way you get a dynamic
> filehandle, so:
>
> perldoc -q filehandle
>
> How can I make a filehandle local to a subroutine? How do I pass
> file-
> handles between subroutines? How do I make an array of filehandles?
>
> 3) There is an already-invented (and tested) wheel for doing
> recursive directory searching, the File::Find module.
The only thing that sometimes puts me off using modules for relatively
simple things like this, is that I wonder how much extra resources they use
or whether they compromise performance in some way. That is, File: Find must
be quite a sizable module with a stack of function/options, so couldn't that
mean lots more memory to run, or is that an incorrect presumption?
> You can read the module's docs with:
>
> perldoc File::Find
>
>
>>================
>> #use strict;
>
>
> You lose all of the benefits of that statement when you comment it out!
yes, I know - I had it commented out to double check that the script worked
without use strict.
>> my $basedir = "j:/files/sw-test";
>> my $fcount = 0;
>> my $fsize = 0;
>> my $dcount = 0;
>> dircount();
>>
>> sub dircount {
>> my($cdir) = shift;
>
>
> $cdir will be undef for the top-level call.
>
>
>> $cdir .= "/" if $cdir ne "";
>
>
> You have all of the path components separated already, so I'd
> paste the dir separator in myself on each usage instead of
> burying one inside of a variable's value.
there was a reason I did that, but I can't recall what it was now (bear with
me - it's nearly home-time and my brain is frazzled!)
>> my $dh = "DH" . length($cdir);
>> opendir($dh,"$basedir/$cdir");
>
>
> You get a dynamic dirhandle when the variable is undef.
>
> Your variable is not undef, so there is no dynamic dirhandle...
>
>
> You should always check the return value to see if you actually
> got what you asked for:
>
> opendir($dh,"$basedir/$cdir") or die "could not open '$basedir/$cdir'
> $!";
>
>
>> while(my $fl = readdir($dh)){
>> next if $fl =~ /^\.{1,2}$/;
>> if(-d "$basedir/$cdir$fl"){
>> $dcount++;
>> dircount("$cdir$fl");
>
>
> If $fl is a symlink to a "higher" directory, then your
> code will go into an infinite loop here.
it's a script that will only run on my Windows servers, so that wasn't an
issue
> Applying the minimum changes to fix (IMO) your code, I get:
>
> ------------------------
> #!/usr/bin/perl
> use warnings;
> use strict;
>
> my $basedir = '/home/tadmc/temp';
> my $fcount = 0;
> my $fsize = 0;
> my $dcount = 0;
> dircount();
>
> sub dircount {
> my($cdir) = shift || '';
that's a neat way of avoiding getting a warning (yes, I did have use
warnings in there for a while :-).. is there any particular reason you use
single quotes there instead of double quotes? I tend to use "" for pretty
much everything. Also, I don't ever seem to use "||" - "or" would work as
well in that scenario wouldn't it?
> opendir(my $dh,"$basedir/$cdir") or die "could not open dir $!";
> while(my $fl = readdir($dh)){
> next if $fl =~ /^\.{1,2}$/;
> if(-d "$basedir/$cdir/$fl"){
> $dcount++;
> dircount("$cdir/$fl");
> }
> else{
> $fcount++;
> $fsize += -s "$basedir/$cdir/$fl";
> }
> }
> close($dh);
> }
>
> print "$fcount files and $dcount directories totalling $fsize bytes in
> size\n";
> ------------------------
>
>
>
> Recasting it to use the tried-and-true module, I get:
>
> ------------------------
> #!/usr/bin/perl
> use warnings;
> use strict;
> use File::Find;
>
> my $basedir = '/home/tadmc/temp';
> my $fcount = 0;
> my $fsize = 0;
> my $dcount = 0;
> find( \&dircount, $basedir );
>
> sub dircount {
> return if $_ eq '.' or $_ eq '..';
> $dcount++ if -d;
> return unless -f; # only care about plain files at this point
> $fcount++;
> $fsize += -s;
> }
>
> print "$fcount files and $dcount directories totalling $fsize bytes in
> size\n";
> ------------------------
thanks
Ian
------------------------------
Date: 22 Dec 2005 18:20:27 GMT
From: Glenn Jackman <xx087@freenet.carleton.ca>
Subject: Re: Dynamic directory handles?
Message-Id: <slrndqlrjc.pbr.xx087@smeagol.ncf.ca>
At 2005-12-22 12:32PM, IanW <whoever@whereever.com> wrote:
> "Tad McClellan" <tadmc@augustmail.com> wrote in message
> news:slrndqlck1.71n.tadmc@magna.augustmail.com...
>
> >> #use strict;
> >
> > You lose all of the benefits of that statement when you comment it out!
>
> yes, I know - I had it commented out to double check that the script worked
> without use strict.
If your code runs with strict, it will certainly run without.
[...]
> > my($cdir) = shift || '';
>
> that's a neat way of avoiding getting a warning (yes, I did have use
> warnings in there for a while :-).. is there any particular reason you use
> single quotes there instead of double quotes? I tend to use "" for pretty
> much everything. Also, I don't ever seem to use "||" - "or" would work as
> well in that scenario wouldn't it?
I use single quotes to remind myself (and perl) that I have a literal
string that needs no interpolation.
'||' and 'or' have different operator precedences. Note also that '||'
has higher precendence than '=' which is higher than 'or'. So,
my($cdir) = shift || '';
is the same as
my($cdir) = (shift || '');
Test:
$x = undef || 'alternate';
print '$x is ', (defined $x ? "'$x'" : 'undefined!'), "\n";
Conversly,
my($cdir) = shift or '';
is the same as
( my($cdir) = shift ) or '';
and thus $cdir may still be undefined.
Test:
$y = undef or 'alternate';
print '$y is ', (defined $y ? "'$y'" : 'undefined!'), "\n";
Another way of proving default values is the '||=' operator, as in:
my $cdir = shift;
$cdir ||= ''; # set cdir to the empty string if previously undefined.
--
Glenn Jackman
Ulterior Designer
------------------------------
Date: Fri, 23 Dec 2005 08:15:06 +1300
From: "Tintin" <tintin@invalid.invalid>
Subject: Re: Dynamic directory handles?
Message-Id: <LWCqf.9970$vH5.490883@news.xtra.co.nz>
"IanW" <whoever@whereever.com> wrote in message
news:doenus$765$1@blackmamba.itd.rl.ac.uk...
> > 3) There is an already-invented (and tested) wheel for doing
> > recursive directory searching, the File::Find module.
>
> The only thing that sometimes puts me off using modules for relatively
> simple things like this, is that I wonder how much extra resources they
use
> or whether they compromise performance in some way. That is, File: Find
must
> be quite a sizable module with a stack of function/options, so couldn't
that
> mean lots more memory to run, or is that an incorrect presumption?
The "overhead" of File::Find is absolutely miniscule. Wouldn't you rather
write efficient code using tried and true
methods, rather than the "overhead" of hacking your own code?
------------------------------
Date: 22 Dec 2005 11:40:26 -0800
From: Rich <rich@newsguy.com>
Subject: Re: getting info from a bash shell script into perl variables
Message-Id: <doevfa015vq@drn.newsguy.com>
In article <pan.2005.12.21.20.29.46.571824@dont.spam.me>, Bob says...
>
>On Wed, 21 Dec 2005 11:36:09 -0800, Rich wrote:
>
>> If you are trying to capture the results of the shell script into an
>> array, something like this might work
>>
>> my @results = `./myscript.sh`;
>>
>> That way you'd have an ordered array, and can use a for loop to look
>> through the results to find what you needed from the shell script.
>>
>> Rich
>
>I settled on the following...
>
>chomp(my @my_info=split /\|/, qx{./my_script.sh});
Thanks for the "unintentional" tip using "qx{./my_script.sh}". Don't normally
use that method and forced me to look it up.
Thanks,
Rich
--
Newsguy -- http://newsguy.com
------------------------------
Date: 22 Dec 2005 11:14:07 -0800
From: Patrick Flaherty <Patrick_member@newsguy.com>
Subject: Re: line-oriented debugger
Message-Id: <doettv011qa@drn.newsguy.com>
In article <eFjqf.40685$tV6.10462@newssvr27.news.prodigy.net>, Todd W says...
>
>
>"Patrick Flaherty" <Patrick_member@newsguy.com> wrote in message
>news:doa43n0i67@drn.newsguy.com...
>> Hi,
>>
>> The 'original' debugger. I've looked all over the place and haven't yet
>been
>> able to answer this question.
>>
>> I've liked to be able to issue two commands at once (well
>one-after-the-other
>> from a single cmd line). As in DB<3> below:
>>
>> DB<2> b 101
>> DB<3> c ; p $i
>>
>> Is this possible?
>>
>
>I think so.
>
>Theres probably a way to do it with the 'a' command. Also, dont forget that
>you can run any perl code any time you want in the debugger (say you want to
>change the value of a variable, or call a method on an object).
>
>So you could change your debugging commands to:
>
>> DB<2> b 101
>> DB<3> a 101 print "\$i is $i\n"
>
>and when you hit "c" you will be sitting at your breakpoint with the
>variable already pretty printed for you :).
>
>$ cat dbg.pl
>use warnings;
>use strict;
>
>my $var1 = 'foo';
>my $var2 = 'bar';
>my $var3 = 'baz';
>
>print("Done\n");
>
>
>$ perl -d dbg.pl
>
>Loading DB routines from perl5db.pl version 1.28
>Editor support available.
>
>Enter h or `h h' for help, or `man perldebug' for more help.
>
>main::(dbg.pl:4): my $var1 = 'foo';
> DB<1> a 6 print "\$var2 is: $var2\n"
> DB<2> b 6
> DB<3> c
>main::(dbg.pl:6): my $var3 = 'baz';
>$var2 is: bar
> DB<3> c
>Done
>Debugged program terminated. Use q to quit or R to restart,
> use O inhibit_exit to avoid stopping after program termination,
> h q, h R or h O to get additional info.
>
>Enjoy,
>
>Todd W.
>
>
>
Todd,
After posting I'd gone through the help items once again more closely and
spotted 'a' as a possible candidate. Although if it was going to do what I
wanted, it was going to do it in a fashion that wasn't quite what I'd originally
thought of. But haven't since then had time to follow-up (and had completed the
particular perl program I was currently working on).
Also then - could one extend 'a' to do, say, three commands (as opposed to two)?
As I reread 'a' yet again, it seems you can only do this if the nature of the
problem is such that you're attaching all commands n+1, n+2, etc to specific
lines.
thanx for your help.
pat
------------------------------
Date: 6 Apr 2001 21:33:47 GMT (Last modified)
From: Perl-Users-Request@ruby.oce.orst.edu (Perl-Users-Digest Admin)
Subject: Digest Administrivia (Last modified: 6 Apr 01)
Message-Id: <null>
Administrivia:
#The Perl-Users Digest is a retransmission of the USENET newsgroup
#comp.lang.perl.misc. For subscription or unsubscription requests, send
#the single line:
#
# subscribe perl-users
#or:
# unsubscribe perl-users
#
#to almanac@ruby.oce.orst.edu.
NOTE: due to the current flood of worm email banging on ruby, the smtp
server on ruby has been shut off until further notice.
To submit articles to comp.lang.perl.announce, send your article to
clpa@perl.com.
#To request back copies (available for a week or so), send your request
#to almanac@ruby.oce.orst.edu with the command "send perl-users x.y",
#where x is the volume number and y is the issue number.
#For other requests pertaining to the digest, send mail to
#perl-users-request@ruby.oce.orst.edu. Do not waste your time or mine
#sending perl questions to the -request address, I don't have time to
#answer them even if I did know the answer.
------------------------------
End of Perl-Users Digest V10 Issue 8787
***************************************