Comparing a string to filenames in a directory

N

nj_perl_newbie

I apologize for posting such a basic question...I have spent a
substantial ammount of time reading thick books trying to figure out
how to do this.

The goal is to read the second field in a text file and compare that
string to a list of filenames in a directory.

So use submits a file with "foo, test.txt" the script will look for
"test.txt" in the directory, if it exists it will copy test.txt to a
different directory.


Here's what I have:

opendir(DIR, $limbodir);
&log_entry($logfh,"Opening Limbo Directory"); if $debug;
@files = grep { /\.csv$/ } readdir(DIR);
&log_entry($logfh, "Files in limbodir read") if $debug;
closedir(DIR);

open (FILE, "$cnfrm_file") || die();

($line)= <FILE>; #Read only the first line into the input file.

while (<FILE>) { #not sure if the while is needed

my @line = split /\,/, $_;
my($firstfield, $filename, $junk) = @line;

unless ( $firstline ) {
#attempts to match the filename submitted in the confirm file with
an already existing input file in the limbo directory
if ( $filename) {
( $filename =~ m/^@files/i ) {
&log_entry($logfh, "Confirm submitted by $username for input
file $path/$basename ");
move ("$_", "$transdir/$basename") || die "move failed: $!";
&log_entry($logfh, "$_ moved to $transdir");
chown 23456,23458, "$transdir/$_" || warn $!;
}

Thanks
 
J

Jürgen Exner

nj_perl_newbie said:
I apologize for posting such a basic question...I have spent a
substantial ammount of time reading thick books trying to figure out
how to do this.

The goal is to read the second field in a text file and compare that
string to a list of filenames in a directory.

So use submits a file with "foo, test.txt" the script will look for
"test.txt" in the directory, if it exists it will copy test.txt to a
different directory.


Here's what I have:

You are missing
use strict;
use warnings;
opendir(DIR, $limbodir);
&log_entry($logfh,"Opening Limbo Directory"); if $debug;

What's the ampersand doing there? Or are you still programming Perl4?
What is the semicolon doing in the middle of the line?
@files = grep { /\.csv$/ } readdir(DIR);
&log_entry($logfh, "Files in limbodir read") if $debug;
closedir(DIR);

From the program logic this whole readdir section above is not needed.
It is much easier to use "-e" later.
open (FILE, "$cnfrm_file") || die();

You may want to get into the habit of using the lower-priority "or" operator
instead of "||".
Also, you will get much better error messages if you include some text, the
error code, and the file name with your die() statement:
open (FILE, "$cnfrm_file") or die("Cannot open file $dnfrm_file because
$!\n");
($line)= <FILE>; #Read only the first line into the input file.

Well, I would have made the comment
# skipping first line
because that is what you are doing.
However, do you really want to skip the first line?
while (<FILE>) { #not sure if the while is needed

Do you want to read the whole file line by line?
my @line = split /\,/, $_;

No need to escape the comma. It is not a special character in a RE.
my($firstfield, $filename, $junk) = @line;

Clearer in my opinion would be
my (undef, $filename, undef) = split /,/;
Then there is no missunderstanding about if you ever use $firstfield and
$junk.
unless ( $firstline ) {

I don't understand what you are trying to do here? Why are you testing if
$firstline evaluates to true?
#attempts to match the filename submitted in the confirm file with
an already existing input file in the limbo directory
if ( $filename) {

I don't understand what you are trying to do here, either? Why are you
testing if $filename evaluates to true?
( $filename =~ m/^@files/i ) {

If you just want to test if a file with the name $filename exists then just
use a simple
if (-e $filename) {
&log_entry($logfh, "Confirm submitted by $username for input
file $path/$basename ");
move ("$_", "$transdir/$basename") || die "move failed: $!";
&log_entry($logfh, "$_ moved to $transdir");
chown 23456,23458, "$transdir/$_" || warn $!;
}

HTH

jue
 
N

nj_perl_newbie

Thanks for the quick feedback.

I have made some edits based on your suggestions, and I have a better
unserstanding of what was happening in the script. I still do not
understand how the script knows that it should compare the second
field in the file to the filenames in the limbo dir.

# Opens limbodir and reads the filenames for later comparison
&log_entry($logfh,"About to open limbodir") if $debug;
opendir(DIR, $limbodir);
chdir("$limbodir") or die "Could not cd into $limbodir: $!\n";
&log_entry($logfh,"Opening Limbo Directory") if $debug;
#@files = grep { /\.csv$/ } readdir(DIR);
#&log_entry($logfh, "Files in limbodir read") if $debug;
#closedir(DIR);

open (FILE, "$input_file") or die("Cannot open file $dnfrm_file
because
$!\n");

while (<FILE>) { #not sure if the while is needed

#my @line = split /\,/, $_;
#my($firstfield, $filename, $junk) = @line;
my (undef, $filename, undef) = split /,/;
unless ( $firstline ) {
#attempts to match the filename submitted in the confirm file with
an already existing input file in the limbo directory
if (-e $filename) {
&log_entry($logfh, "Confirm submitted by $username for input
file $path/$basename ");
move ("$_", "$transdir/$basename") or die "move failed: $!";
&log_entry($logfh, "$_ moved to $transdir");
chown 23456,23458, "$transdir/$_" or warn $!;
}
undef $firstline;
 
T

Tad McClellan

nj_perl_newbie said:
I apologize for posting such a basic question...I have spent a
substantial ammount of time reading thick books trying to figure out
how to do this.


Have you seen the Posting Guidelines that are posted here frequently?

Here's what I have:

opendir(DIR, $limbodir);
&log_entry($logfh,"Opening Limbo Directory"); if $debug;
^^^^

That is not Perl code.

If you need help with your Perl program, then you should post
the actual Perl program.

If your question is about the syntax error, then you should ask
a question about the syntax error.

my @line = split /\,/, $_;
my($firstfield, $filename, $junk) = @line;


The @line temporary variable is not needed:

my($firstfield, $filename, $junk) = split /\,/, $_;

or even

my($firstfield, $filename) = split /\,/, $_;

chown 23456,23458, "$transdir/$_" || warn $!;


It is easier to work with permissions if you think in octal
rather than in decimal...
 
R

Richard Morse

Thanks for the quick feedback.

I have made some edits based on your suggestions, and I have a better
unserstanding of what was happening in the script. I still do not
understand how the script knows that it should compare the second
field in the file to the filenames in the limbo dir.

# Opens limbodir and reads the filenames for later comparison
&log_entry($logfh,"About to open limbodir") if $debug;
opendir(DIR, $limbodir);
chdir("$limbodir") or die "Could not cd into $limbodir: $!\n";
&log_entry($logfh,"Opening Limbo Directory") if $debug;
#@files = grep { /\.csv$/ } readdir(DIR);
#&log_entry($logfh, "Files in limbodir read") if $debug;
#closedir(DIR);

open (FILE, "$input_file") or die("Cannot open file $dnfrm_file
because
$!\n");

while (<FILE>) { #not sure if the while is needed

#my @line = split /\,/, $_;
#my($firstfield, $filename, $junk) = @line;
my (undef, $filename, undef) = split /,/;
unless ( $firstline ) {
#attempts to match the filename submitted in the confirm file with
an already existing input file in the limbo directory
if (-e $filename) {
&log_entry($logfh, "Confirm submitted by $username for input
file $path/$basename ");
move ("$_", "$transdir/$basename") or die "move failed: $!";
&log_entry($logfh, "$_ moved to $transdir");
chown 23456,23458, "$transdir/$_" or warn $!;
}
undef $firstline;

How about this:

use strict;
use warnings;

opendir(my $dir, $limbodir) or die("could not opendir $limbodir: $!");
my @files = grep { /\.csv$/ } readdir($dir);
closedir($dir);

open(my $file, "<", $dnfrm_file) or die("could not open $dnfrm_file:
$!");

while(<$file>) {
chomp;
my ($firstfield, $filename, $rest) = split /,/;
if (defined($filename) and ($filename ne '') and
(-e "$limbodir/$filename") {
move("$_", "$transdir/$basename") or die("move failed: $!");
}
}

I'm not too sure about some of the steps you are taking -- that move
call seems a bit complicated -- but this might be a bit clearer...

HTH,
Ricky
 
B

Ben Morrow

It is easier to work with permissions if you think in octal
rather than in decimal...

chown, not chmod... :)

It's likely to be more future-proof if you get the [ug]id using
get{pw,gr}nam.

Ben
 
T

Tintin

nj_perl_newbie said:
Thanks for the quick feedback.

Who are you talking to? Please learn how to reference, attribute and quote
correctly.
I have made some edits based on your suggestions, and I have a better
unserstanding of what was happening in the script.

Unfortunately, you ignored most of the good suggestions.
I still do not
understand how the script knows that it should compare the second
field in the file to the filenames in the limbo dir.

[snip of essentially the same script as the original]
 
N

nj_perl_newbie

Okay, thank you all for your suggestions. I realise that I reposted a
couple of the same syntax errors and I apologize if that caused any
confusion.

Tintin: I was thanking Jurgen for his quick feedback, at the time he
was the only person who replied to my post.

Ricky: thanks for your help this looks like a nice suggestion

Tad, I have not yet read the posting guidlines, I will search for them
today. My original question wasn't really about the syntax of the
program. I know that I had a few random ;s, I was originally asking
how one would approach this problem using Perl's text processing
features.

Thank you all of your sugestions, I will play with this some more
today.
 
N

nj_perl_newbie

Okay, this is what I ended up with:

I get some warnings when it is run and I am still not able to run it
in "Taint mode", but it is moving the file. I am not receiving
e-mails so I don't think that the call to &mail is working properly.
Any thoughts?

sub chx_file { # moves change files associated with a confirmation
file to the transfer directory
#
#
use File::Basename;

my($email,$csv_path,$type) = @_;

my $input_file = &untaint_pathname($csv_path);
my $basename = &untaint_filename( basename($input_file,"\.csv") );
&log_entry($logfh, "sub chx_file") if $debug;
&log_entry($logfh, "input_file is: $input_file") if $debug;

open (FILE, "$input_file") or die("Cannot open file $input_file
because $!\n");

chdir($limbodir) or die "cannot cd to limbodir ($!)";
while (<FILE>) {
chomp;
my ($firstfield, $filename, $rest) = split /,/;
&log_entry($logfh, "limbo files are $limbodir/$filename");
&log_entry($logfh, "filename is: $filename");
if (defined($filename) and ($filename ne '') and (-e "$filename"))
{
move("$filename", "/export/ftp/transfer/") or die("move failed:
$!");
&log_entry($logfh, "File $filename moved");
&mail(
recipient => $email,
subject => "BulkAdmin input file $filename queued for production.",
body => "The BulkAdmin input file: $filename has been queued for
production.\n\nThis file will now be stored in the transfer directory
and will be run in production at 7:00 AM GMT \n\nAn email will be sent
to you after results are available.\n",
);
}
else {
&log_entry($logfh, "Confirm file doesn't match any files in
limbo directory");
}
}
}
 
J

J. Gleixner

nj_perl_newbie said:
Okay, this is what I ended up with:

I get some warnings when it is run and I am still not able to run it
in "Taint mode", but it is moving the file. I am not receiving
e-mails so I don't think that the call to &mail is working properly.
Any thoughts?

Since you're not getting "mail", it's obviously the call to mail() (note
the absence of &) isn't working. Since you don't provide that code or
test what mail() returns, who knows.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,043
Latest member
CannalabsCBDReview

Latest Threads

Top