Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer

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 avoiding work at the Monastery: (5)
As of 2018-07-16 01:00 GMT
Find Nodes?
    Voting Booth?
    It has been suggested to rename Perl 6 in order to boost its marketing potential. Which name would you prefer?

    Results (330 votes). Check out past polls.