in reply to Re^2: Read from multiple files change the data with a script and the write the respective output files with a different extension
in thread Read from multiple files change the data with a script and the write the respective output files with a different extension

You have many files and want to process one at a time, so use a loop:

my @files = glob '*.txt'; for my $name (@files) { my $new_file = $name =~ s/txt$/csv/r; process_file($name, $new_file); }
  • Comment on Re^3: Read from multiple files change the data with a script and the write the respective output files with a different extension
  • Download Code

Replies are listed 'Best First'.
Re^4: Read from multiple files change the data with a script and the write the respective output files with a different extension
by Akatsuki (Novice) on Oct 13, 2016 at 13:54 UTC

    If you could help me with another problem I encountered in this program I would be very grateful. I want to enter the number of columns, only once for all the files, not for every file. My original code is:

    while (my $line = <$original_fh>) { print "Enter the desired number of columns: "; my $nr = <STDIN>; chomp($nr); $line =~ s/((\w\w\t){$nr})/$1\n/g; $line =~ s/\t/,/g; $line =~ s/(\d{2})/$replace[$1]/g; print $final_fh $line; }

    and I tried something like this unsuccessfully

    while (my $line = <$original_fh>) { for my $file (@files) { print "Enter the desired number of columns: "; my $nr = <STDIN>; chomp($nr); $line =~ s/((\w\w\t){$nr})/$1\n/g; } $line =~ s/\t/,/g; $line =~ s/(\d{2})/$replace[$1]/g; print $final_fh $line; }

      There are 2 key conceptual problems here.

      Firstly you reference @files in a location where it has not been declared. You need to consider scoping with regard to subs.

      Secondly, you have put your new code inside a for loop which is itself inside a while loop. Can you explain why you think this means it would only be executed once?

        Thank you for your answer. To be clear, I want this statement: print "Enter the desired number of columns: "; to be printed just once in the begining of the program for all the files inside the folder, right now it asks for every file.

      Think about the flow of work in words. When you have something that make sense in words, you just need to translate it into Perl code.

      You say: "and I tried something like this unsuccessfully"

      while (my $line = <$original_fh>) { for my $file (@files) { print "Enter the desired number of columns: "; my $nr = <STDIN>; chomp($nr); $line =~ s/((\w\w\t){$nr})/$1\n/g; }

      If you translate this in plain english it sounds like: while is true that I can read a line from this file, for each file I have, ask me how many column I must consider. It does make no big sense.

      You want firstly ask how many column to consider, then for each file obtain the output filename, open it and foreach line do some transformation. Right?

      Now in plain english (if my english can be plain..) your overall program must resemble to something like this TODO list:

      • Fill @files using glob
      • decide how many column are desired (ask the user or hardcode in the program)
      • foreach @files compose the name of the output file ( my $new_file = $name =~ s/txt$/csv/r; ), open a new file in in write mode open( my $final_fh,    ">", $final )    or die $!; then open the source file for reading and foreach line make some transformation and write the line to the output file. When input file is finished, clean up ie close the pair of files and pass to next source one.
      When you have the basic flow of the program working you can add some brick here and there to make it more robust: what happen if I cant read? you yet added or die $! and this is good. What happen if an output file already exists?

      Notice also that a practical way to ask user for something can be accomplished in a cleaner and less verbose way giving your program the ability to parse command line arguments: two core module are devoted to such tasks: Getopt::Std that is basic and the more developped Getopt::Long

      HtH

      L*

      There are no rules, there are no thumbs..
      Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.

        Thank you for yor help, but there are still some things I didn't understand...so this is my code:

        #!/usr/bin/perl use warnings; use strict; sub process_file { my ($original, $final) = @_; open( my $original_fh, "<", $original ) or die $!; open( my $final_fh, ">", $final ) or die $!; my $first = <$original_fh>; print $final_fh $first; my @replace = $first =~ /"([^"]*)"/g; while (my $line = <$original_fh>) { print "Enter the desired number of columns: "; my $nr = <STDIN>; chomp($nr); $line =~ s/((\w\w\t){$nr})/$1\n/g; $line =~ s/\t/,/g; $line =~ s/(\d{2})/$replace[$1]/g; print $final_fh $line; } close $original_fh; close $final_fh; } my @files = glob '*.bit'; for my $name (@files) { my $new_file = $name =~ s/bit$/csv/r; process_file($name, $new_file); }

        so I used glob to fill @files, the statement to ask the user has to be in the while loop so it can transform the files by the number entered(after I finish the working code I will make it more robust and cautious) and the source for read and output for write are opened so I don't think I have to open them again. Do you have any advice for my specific code so I can finally understand? Thank you for your effort!

Re^4: Read from multiple files change the data with a script and the write the respective output files with a different extension
by Akatsuki (Novice) on Oct 13, 2016 at 12:02 UTC

    Thank you very much for your help. It's all clear now.