http://www.perlmonks.org?node_id=1008518

Vijay81 has asked for the wisdom of the Perl Monks concerning the following question:

Hi All,

Am trying to read directory/subdirectories and for files from a path recursively. Once file found in any directory, reading file content(usually just 1 line in a file) and substituting space with comma from the line. then I need to pass the values to another sub functions.

Problem : 1. line number 35 doesn't seems to be working. when i try to print $line, it doesn't show anything/value. 2. Need to pass @columns/@filenames/@dir_names to the sub function(&write_output) called in line number 46.

Can someone tell me where am doing wrong and help me out

I need to know is there any tool/utlity for Windows XP where in which in can run the perl script line by line debugging mode so, that i can see what's happen to the variables during run time.

Many Thanks...
#! /usr/bin/perl use warnings; use strict; use File::Find; use File::Basename; my $base_dir = 'C:\Perl\TestData'; my (@columns,@dirs,@buf,@dir_names,@filenames); my ($dir,$file,$resultxmlfile,$line,$fh); $line=''; sub process_files { print "dive into: $_[0]\n"; opendir DIR, $_[0] or die "Could not open directory"; print $_[0]; print "\n"; @dirs = readdir DIR; closedir DIR; foreach $file (@dirs) { if ($file =~ /\.{1,2}/) {next } print "processing: $file\n"; if ( -d "$_[0]/$file" ) { process_files ("$_[0]/$file"); push(@dir_names, basename($file)); print @dir_names; print "\n"; foreach my $file (@dirs){ print $file; next if $file eq '.' or $file eq '..'; print "\n"; open (FILE, "<", $file) or die "Could not open file -- $_[0] +/$file"; @buf = <FILE>; foreach $line (@buf) { $line = <FILE>; # this line doesn't work. don't know w +hat's wrong here.. $line=~ s/ /,/g; print $line; push(@columns,$line); print @columns; print "\n"; $file =~ s/.*\///; $file =~ s/\.[^.]+$//; push(@filenames, $file); print @filenames; } &write_output; # need to pass @columns/@filenames/@dir +_names values to this function close FILE; } } } } process_files $base_dir;

Replies are listed 'Best First'.
Re: process a file and reading a line and passing the values to another sub function
by LanX (Saint) on Dec 12, 2012 at 16:28 UTC
    please try to condense code to the relevant parts or mark them better.

    I really started counting the lines till 35 before I saw your comment.

    something like:

    $line = <FILE>; # <---------- 35 # this line doesn't work. don't know what's wrong here..

    is easier to find.

    anyway, you did it twice:

    @buf = <FILE>; # you reading all lines of FILE i +nto @buf foreach $line (@buf) { # OK! (well, "my $line" would be +better) $line = <FILE>; # but now reading again a single +line !?! # which is undef after EOF

    please less cargo cult programming!

    Don't c&p different approaches from other snippets, better try to understand what's happening.

    Cheers Rolf

Re: process a file and reading a line and passing the values to another sub function
by marto (Cardinal) on Dec 12, 2012 at 15:48 UTC

    "I need to know is there any tool/utlity for Windows XP where in which in can run the perl script line by line debugging mode so, that i can see what's happen to the variables during run time."

    Perl has a debugger, learn how to use it here: perldebtut.

Re: process a file and reading a line and passing the values to another sub function
by 2teez (Vicar) on Dec 12, 2012 at 16:43 UTC

    Hi Vijay8l,
    Am trying to read directory/subdirectories and for files from a path recursively

    Why not use File::Find instead of doing all the jobs yourself.

    ..reading file content(usually just 1 line in a file) and substituting space with comma from the line.
    Are you trying to create a Comma-separated values files? If yes then see Text::CSV.

    Just to give a head up, using File::Find and substitution function, I did something very close to what you wanted.

    #!/usr/bin/perl use warnings; use strict; use File::Find; my $base_dir = '...'; # put in your base directory find( \&wanted, $base_dir ); sub wanted { return if $_ eq '.' or $_ eq '..'; if (-d) { print " >>> dive into: $_\n" if -d; } else { readout_file($_); ## call subroutine readout_file } } sub readout_file { my ($filename) = @_; open my $fh, '<', $filename or die "can't open file:$!"; while (<$fh>) { chomp; s/ /,/; ## OR s/ /,/g; if you want print $_, $/; ## OR any other subroutine you want } }

    Update:
    Seriously, Please look into Text::CSV if csv files are intended.
    If you tell me, I'll forget.
    If you show me, I'll remember.
    if you involve me, I'll understand.
    --- Author unknown to me
Re: process a file and reading a line and passing the values to another sub function
by blue_cowdawg (Monsignor) on Dec 12, 2012 at 18:38 UTC

    As mentioned elsewhere you can use find2perl to create a skeleton program for you that does the job very well. But here's a piece of code I have laying around that may or may not work for what you want to do.

    #!/usr/bin/perl -w ###################################################################### +## use strict; my $start="/some/path/to/some/where"; crawl($start); exit(0); sub crawl { my $dir = shift; opendir(my $dh,$dir) or die "$dir: $!"; while (my $entry=readdir($dh)){ next if ($entry eq '.') || ($entry eq '..'); printf "%s\n",$entry; if ( -d $entry ) { crawl($dir . "/" . $entry); } } closedir($dh); }
    Now... them's the basics...

    Embelish the output or actions as you need. For instance if I were to use this "real time" I'd add an indentation element or even ASCII art elements to it to make the output more useful.

    HTH


    Peter L. Berghold -- Unix Professional
    Peter -at- Berghold -dot- Net; AOL IM redcowdawg Yahoo IM: blue_cowdawg
Re: process a file and reading a line and passing the values to another sub function
by Vijay81 (Acolyte) on Dec 13, 2012 at 20:46 UTC

    ok, finally i found out that we can use split function to put the comma seperated line into array element.

    </codesub readout_file { my ($filename) = @_; my (@linecolumns); open my $fh, '<', $filename or die "can't open file:$!"; while (<$fh>) { chomp; ~s/ /,/g; ## OR s/ /,/g; if you want print $_, $/; @linecolumns = split(',',$_); #print $_, $/; ## OR any other subroutine you want print $linecolumns[0],$/; print $filename, $/; } }
Re: process a file and reading a line and passing the values to another sub function
by Vijay81 (Acolyte) on Dec 13, 2012 at 14:27 UTC

    Thanks Everyone. @2Teez, what you suggested is what i was looking but now, when put $line conent to some array after doing csv(somma seperated), am not able to get any values to $line or @linecolumns. Can you please suggest help me on how to get the $line value into some array so, that i can pass that array element/value to another sub function.

    #!/usr/bin/perl use warnings; use strict; use File::Find; my $base_dir = 'C:\\TestData'; # put in your base directory my ($dirname,$filename,$line); my (@linecolumns); find( \&wanted, $base_dir ); sub wanted { return if $_ eq '.' or $_ eq '..'; if (-d) { print " >>> dive into: $_\n" if -d; $dirname = $_; } else { readout_file($_); ## call subroutine readout_file } } sub readout_file { my ($filename) = @_; open my $fh, '<', $filename or die "can't open file:$!"; while ($line=<$fh>) { chomp; $line=~s/ /,/g; ## OR s/ /,/g; if you want print $line, $/; push(@linecolumns,$line); #print $_, $/; ## OR any other subroutine you want print $linecolumns[0], $/; print $filename, $/; #write_output($dirname,$filename,$linecolumns[0],$linecolumns[3]); ## +call subroutine to print std template in output file } }