Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw

Re: looping logic error while printing output from folder/flie content

by graff (Chancellor)
on Dec 15, 2012 at 03:35 UTC ( #1008930=note: print w/ replies, xml ) Need Help??

in reply to looping logic error while printing output from folder/flie content

You seem to have several problems. First, the XML data you're writing is badly formed. Your "container" tags don't have close tags, your "login" tag has two close tags, and your initial <?xml...> line is declaring "utf-16" encoding, but you don't seem to be writing any utf-16 data (and you probably don't want to) - either leave that line out, or say "utf-8". And you appear to be concatenating a bunch of complete xml streams into one file, which I believe will be rejected by any normal xml parser.

Second, you are doing too much work trying to keep track of the directory depth yourself - File::Find gives you the path to each file name that it passes to your "wanted" function, so you just need to break that up into the various directory levels.

Third, you're wasting time with unnecessary operations (repeated use of the "-d" function, repeatedly opening an output file, pushing $filename onto an array every time a line is read from a data file, etc).

Also, you are writing data into an output file in the same directory that File::Find is scanning, so your output is going to be read as input (which is likely to give you strange results).

Let me suggest the following - it differs a fair bit from the OP code in terms of how the output is structured, but since the OP output is badly formed, I'm just guessing at the kind of output you really want. It hasn't been tested, of course (since I don't have your data files), but it does compile.

Note that there's just one subroutine (process_file) for reading and writing content from your data files - that just makes more sense, since the stuff being read needs to go directly to the output. Also, the nesting of "container" tags should reflect the nesting of directories (which I think is probably what you intended to get, eventually).

#!/usr/bin/perl use strict; use warnings; use File::Find; my $basedir = "C:/Test"; open( my $resultfile, '>', 'C:/SomewhereElse/resultfile.dat' ) or die +"resultfile.dat: $!"; # the next bit should only be written one time per xml output file: print $resultfile <<EOH; <?xml version="1.0" encoding="UTF-8"?> <!-- ****************************************************************- +-> <!-- * *- +-> <!-- * PuTTY Configuration Manager save file - All right reserved. *- +-> <!-- * *- +-> <!-- ****************************************************************- +-> <!-- The following lines can be modified at your own risks. --> <configuration version="" savepassword="True"> <root type="database" name="$basedir" expanded="True"> EOH my @containers; my $indent = ''; find( \&wanted, $basedir ); if ( @containers ) { for ( 0 .. $#containers ) { print "$indent</container>\n"; chop $indent; } } print $resultfile "</root>\n</configuration>\n"; sub wanted { return if ( /^..?$/ ); if ( -d ) { my ( $root, @levels ) = split m{/}, $File::Find::dir; if ( @levels > @containers ) { # push one level deeper $indent .= " "; print $resultfile "$indent<container type=\"folder\" name= +\"$levels[-1]\" expanded=\"True\">\n"; } elsif ( @levels < @containers ) { # pop out one level print $resultfile "$indent</container>\n"; chop $indent; } elsif ( $levels[-1] ne $containers[-1] ) { # same level, diff +erent path print $resultfile "$indent</container>\n"; print $resultfile "$indent<container type=\"folder\" name= +\"$levels[-1]\" expanded=\"True\">\n"; } @containers = @levels; } elsif ( -f _ and -s _ ) { # Note use of "_" (see 'perldoc -f -X') process_file(); } } sub process_file { my $filename = $_; open my $fh, '<', $filename or die "$File::Find::name : $!\n"; my @linecolumns; while (<$fh>) { chomp; my @linecolumns = split; } print $resultfile <<ETX; $indent<connection type="PuTTY" name="$filename"> $indent <connection_info> $indent <name>$filename</name> $indent <protocol>SSH</protocol> $indent <host>$linecolumns[5]</host> $indent <port>$linecolumns[4]</port> $indent <session>Default Settings</session> $indent <commandline>$linecolumns[9]</commandline> $indent <description /> $indent </connection_info> $indent <login> $indent <password /> $indent <prompt /> $indent </login> $indent <timeout> $indent <connectiontimeout>1000</connectiontimeout> $indent <logintimeout>750</logintimeout> $indent <passwordtimeout>750</passwordtimeout> $indent <commandtimeout>750</commandtimeout> $indent </timeout> $indent <command> $indent <command1 /> $indent <command2 /> $indent <command3 /> $indent <command4 /> $indent <command5 /> $indent </command> $indent <options> $indent <loginmacro>False</loginmacro> $indent <postcommands>False</postcommands> $indent <endlinechar>10</endlinechar> $indent </options> $indent</connection> ETX }
(updated to write any container close tags that are needed after "find()" returns - still, it hasn't been tested)

Comment on Re: looping logic error while printing output from folder/flie content
Select or Download Code

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://1008930]
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others imbibing at the Monastery: (5)
As of 2014-09-30 23:20 GMT
Find Nodes?
    Voting Booth?

    How do you remember the number of days in each month?

    Results (386 votes), past polls