Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris

Nested While Loop Problem

by Smith (Initiate)
on Feb 05, 2009 at 20:58 UTC ( #741691=perlquestion: print w/replies, xml ) Need Help??
Smith has asked for the wisdom of the Perl Monks concerning the following question:

I am doing a nested while loop with filehandlers and getting massive redundancies. Can anyone help me with this?

ActiveStatePerl 5.10.0 Build 1004 (free version)
Coding on WXP using VIM for Windows (unfortunately)

I have a file that contains a list of files and md5hashes.

This is the first while loop using a file handler. A real file will have 200 lines or so.
(sample file list BADFILES.csv)

Im connected to hosts and doing a filescan and for this test the host has the file located in three directories. I was unable to regex this as a variable it would only grab the first c:\ due to the format. So I dumped it to FSOUT.txt and created a second while loop doing a filehandler. This works perfect and grabs all three but created redundancies.
(sample output FSOUT.txt)

Attempting to connect to remote host... Initialising rctrlx server component... Executing remote application: filescan.exe let.exe Stdout: Volume in drive C has no label. Volume Serial Number is 6C3D-BD57 Directory of c:\ 02/04/2009 11:26 AM 0 let.exe 1 File(s) 0 bytes Directory of c:\WINDOWS 02/04/2009 11:31 AM 0 let.exe 1 File(s) 0 bytes Directory of c:\WINDOWS\system32 02/04/2009 11:31 AM 0 let.exe 1 File(s) 0 bytes Total Files Listed: 3 File(s) 0 bytes 0 Dir(s) 27,333,230,592 bytes free Remote application exited with code: 0
Here is the snippet of code with the nested while loops. #!C:\\Perl\\bin\\perl.exe

my $workdir = "c:\\MalwareScanner\\lclscn"; if (! $ARGV[0]){ print "FATAL Didnt get an IP address\n"; $target = <>; } else { $target = $ARGV[0]; } $badfiles = "$workdir\\BADFILES.csv"; $fsout = "$workdir\\FSOUT.txt"; open (BADIN,$badfiles); open (FSOUT,">$fsout"); print HOSTINFO "File,MD5,Ticket,Size,Path\n"; while (<BADIN>){ chomp(); $badline = $_; if ($badline =~ /(.+?),(.+?),.+?,.+?,(.+)/){ $file = $1; $hash = $2; $tckt = $3; } $filescan = `rctrlx.exe $target /u "domain\\username" /p "password +" /c filescan.exe /app filescan.exe $file`; print FSOUT $filescan; if ($filescan =~ /(error.*)/i){ $scanerror1 = $1; print ERROR "$logdate,$logtime,$target,$host,Could not run fil +escan.exe remotely on target host,$scanerror1\n"; } if ($filescan =~ /(.*\d{10})/){ $scanerror2 = $1; print ERROR "$logdate,$logtime,$target,$host,Could not run fil +escan.exe remotely on target host,$scanerror2\n"; } close FSOUT; $fsin = "$workdir\\FSOUT.txt"; open (FSIN,$fsin); while (<FSIN>){ chomp(); $fsline = $_; if ($fsline =~ /(.:\\.*)/){ $dir = $1; print "XXXX$dir\n"; } if ($fsline =~ /1\sFile\(s\)\s+(.*)/){ $size = $1; $size =~ s/[\s]//g; $scanned = "$logdir\\SCANNED.csv"; open (SCANNED,">>$scanned"); print SCANNED "$logdate,$logtime,$target,$host\n"; } print "$dir\n"; $badhost = "$logdir\\BADHOST.csv"; open (BADHOST,">>$badhost"); $dest = "$dir\\$file"; $dest =~ s/[\s]//g; $md5sumtmp = `rctrlx.exe $target /u "domain\\username" /p "pas +sword" /c md5sum.exe /app md5sum.exe $dest`; if ($md5sumtmp =~ /([a-z0-9]{32})/){ $md5sum = $1; } if ($md5sum eq $hash){ print HOSTINFO "$file,$md5sum,$tckt,$size,$dir\n"; print BADHOST "$logdate,$logtime,$target,$host,$file,$md5s +um,$tckt,$size,$dir\n"; } } }
Notice I have two print to STDOUT for testing:
[print "XXXX$dir\n";] [print "$dir\n";]
This is what I get when I run it against the host with the files.

\n \n \n \n \n \n \n \n \n \n \n XXXXc:\ c:\ c:\ c:\ c:\ c:\ XXXXc:\WINDOWS c:\WINDOWS c:\WINDOWS c:\WINDOWS c:\WINDOWS c:\WINDOWS XXXXc:\WINDOWS\system32 c:\WINDOWS\system32 c:\WINDOWS\system32 c:\WINDOWS\system32 c:\WINDOWS\system32 c:\WINDOWS\system32 c:\WINDOWS\system32 c:\WINDOWS\system32 c:\WINDOWS\system32 c:\WINDOWS\system32 c:\WINDOWS\system32
What I need is just the three directory listings c:\ , c:\WINDOWS , c:\WINDOWS\system32.

Replies are listed 'Best First'.
Re: Nested While Loop Problem
by kennethk (Abbot) on Feb 05, 2009 at 21:32 UTC

    You should always start every script with use strict; use warnings;. These are very good ways of avoiding a lot of pointless headaches.

    You could achieve your goal in a fairly straight forward way using hashes. Replace the print statements in your while loop with $count{$dir}++;, which will increment a directory-specific counter. You can then finish your script with print join "\n", keys %count;. For some information on hashes, check out perlintro.

      Thank you very much. Im still a little green on hashes and wasnt sure if it would work in this situation without introducing yet another loop.

      I had the two print statements to show that it prints fine from within the if statement. (it gives me the three directories like it should)
      if ($fsline =~ /(.:\\.*)/){ $dir = $1; print "$dir\n"; #works fine here }
      But if I print outside of the if statement I get the redundancies. And if there are then this command will repeat against the remote host multiple times for the same directory.

      $badhost = "$logdir\\BADHOST.csv"; open (BADHOST,">>$badhost"); $dest = "$dir\\$file"; #will print redundancies here $dest =~ s/[\s]//g; $md5sumtmp = `rctrlx.exe $target /u "domain\\username" /p "password" / +c md5sum.exe /app md5sum.exe $dest`;
        I am having a little difficulty interpreting your question, so if this answer is off point I apologize. I think what is happening is that since you are accessing the $dir variable outside of the conditional loop, you are caching a value of $dir from a previous traverse of the loop. Perhaps this could be fixed with something along the lines of

        if ($fsline =~ /(.:\\.*)/){ $dir = $1; print "$dir\n"; #works fine here } else { next; }

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://741691]
Approved by Corion
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others lurking in the Monastery: (4)
As of 2018-04-22 18:55 GMT
Find Nodes?
    Voting Booth?