Forum Moderators: coopster & phranque

Message Too Old, No Replies

Need filename to pass to <INFILE>

Pass filename and generate name variable from filename to pass to <INFILE>

         

ejazzy

8:55 pm on Jul 20, 2005 (gmt 0)

10+ Year Member



Hi All

I'm a relative newbie to perl, and hit on my third major stumbling block. I'm sure I'm not far off finding a resolution.

I have a list of csv files in my directory. I need to do two things with these files. Firstly, I need to process every file in the directory in one fell swoop. I'm guessing this is possible in that I can pass the filename been sent through <INFILE>. Secondly, I would like to split the filename so it only contains the first part of the filename, e.g, IRCPE.csv will be passed as the parameter to <INFILE> but IRCPE will be used as the $name variable. I'm also guessing I can use split here. Trawling through the web, I've found a way to list the files using opendir and readdir.

This works fine and lists the. Using a Foreach, and this could be where I'm going wrong, I'd like to process each file individually. The problem comes when I try playing with the split. At the moment, I've added the following to my foreach statement, and I've tried different permutation but to no avail.

opendir(DIR, '.') or dir "Cannot open Directory $!";
@file = (grep (/\.csv/,readdir (DIR)));
$file = split /\./, @file;

foreach $file(@file)
{
$name = $file[0];
print "$name\n";

}
closedir (DIR);

I don't get the names instead, I see either a list of numbers, 1-12, as there are 12 files in the directory, or I get the same filename each time which is what that permutation above does or some another error. I actually get a deprecated error as well to do with @_.

The idea ultimately is to generate the names without the *.csv extn and also pass the $file parameter as my <INFILE> setting similar to the following.

open(INFILE, $file) ¦¦ die "Can't open Input File $file";

I'm probably going about this the wrong way but any assistance here would be appreciated as always.

TIA

Regards

moltar

10:10 pm on Jul 20, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



You need to have a look at foreach and split documentation.

opendir(DIR, '.') or die "Cannot open directory: $!"; 
my @files = (grep (/\.csv/, readdir(DIR)));
# deleted this line: $file = split /\./, @file;
foreach my $file (@files) {
# added next line:
my $tr_file = split /\./, $file;
print "$file\n";
# open file for reading only
open(FILE, "< $file") or die "Cannot open $file: $!";

#
# do stuff with the open file
#

# make sure we close it
close(FILE);
}
closedir(DIR);

The changes were highlighted in bold.

WWMike

10:18 pm on Jul 20, 2005 (gmt 0)

10+ Year Member



Here's the list of files in ascending order:

#!/usr/bin/perl

print "Content-type: text/html\n\n";

opendir ( DIR, '.' );
@files = grep ( /\.jpg$/, readdir ( DIR ) );
closedir ( DIR );

@files = sort @files;

foreach $file ( @files ) {
( $name, $ext ) = split /\./, $file;
print "$name<BR>";
}

exit;

ejazzy

11:15 pm on Jul 20, 2005 (gmt 0)

10+ Year Member



Hi Moltar

Firstly thank you. I've followed your suggestions and it's almost there. The problem I'm facing though is that it only reads the first file and nothing else. The expected behaviour was for each file it reads, a temporary file to be created with the same name so at the end, there will be 12 .tmp files created. I've pasted my start and end code here.

#!/usr/bin/perl
use warnings;
use strict;

my $DEBUG = 0;
my (@file, @infile, @items);
my ($file, $name, $line, $curvefile);
my ($term, $termval, $amount);

opendir(DIR, '.') or die "Cannot open directory: $!";
my @files = (grep (/\.csv/, readdir(DIR)));

foreach my $file (@files) {
my $tr_file = split /\./, $file;
print "$file\n";

$curvefile = $file . ".tmp";

open(FILE, "< $file") or die "Cannot open $file: $!";
open (CURVEFILE, ">$curvefile") ¦¦ die "Can't open header output file $curvefile";

my @lines = <FILE>; # slurp all lines from input
chomp @lines; # remove newlines

my $counter = 0;
print CURVEFILE "Zero,ID,Name;

.....

print CURVEFILE "$line\n";
exit 0;

close(FILE);
}
closedir(DIR);

Secondly, what is the relevance of tr_file? I tried using that as the new file name but instead of the value, I get 2. I get the following error which might explain this error.

Use of implicit split to @_ is deprecated at getfile.pl line 18. This is in relation to this line

my $tr_file = split /\./, $file;

moltar

3:13 am on Jul 21, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



It reads only the first file because you exit after processing the file. You don't need
exit 0;
at the end of the loop.

$tr_file
is filename without extension (truncated file) as you asked for it. I made a mistake though, that is why it's giving you errors. It should read
my ($tr_file) = split(/\./, $file);
. Note the brackets around the variable name. You need that because split returns an array of values.

One more thing. You can process files more efficiently if you do not store the entire file in array. Just process them as you go. For example:


open(FILE, "< file.csv");
while (<FILE>) {
# The line is stored in a special variable $_,
# you can reassign it if you wish.
# As you can see it can be avoided
chomp; # same as chomp $_;
print; # same as print $_;
}
close(FILE);

This way you can read files several gigabytes long without it being all in memory. Because if you store something in array, it automatically goes into memory.

SeanW

12:51 pm on Jul 21, 2005 (gmt 0)

10+ Year Member



I see a couple of problems

1. You're parsing the filename outside the loop (ie you read in all the filenames, and don't process them individually)
2. split()ting a filename isn't good practice, what if the file was abc.def.csv?

[perl]
foreach my $fname (<*.csv>) { # glob
($short) = ($fname =~ /(.*)\.csv/); # match everything that's not .csv
unless (open IN, $fname) {
print STDERR "$@ opening $fname";
next; # Why die? The other files might work
}
while (<IN>) {
# Magic happens
}
close IN;
}
[/perl]

SeanW

3:39 pm on Jul 21, 2005 (gmt 0)

10+ Year Member



Just to be pedantic, my regexp should be anchored, ie

[perl]
/(.*)\.csv$/
[/perl]

Sean

ejazzy

5:51 pm on Jul 21, 2005 (gmt 0)

10+ Year Member



Hi guys, I just wanted to say thanks for all your help on this. I've incorporated the changes and the application seems to be working fine now. Thanks