Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations wOOdy-Soft on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

need -> HELP 1

Status
Not open for further replies.

anonimous

IS-IT--Management
Sep 22, 2003
31
CH
hi

I need help, to change this perl script.

I get many times a day 3 TEXT files:
one info file and two data files.
info file looks:
---------------------------------
FA12300011 TN20040203

GA12300012 TT20040203
----------------------------------
this perl script first opens and reads the info file,
renames the first file FA12300011 to TN20040203,
sends via ftp the first file,
waits 15 minutes,
renames the second file GA12300012 to TT20040203
and sends via ftp.
the name of the info file never changed,
but names of these 2 data files YES.

how to change this script ,to check if file names are the same like on the info file ?
otherwise should stop the whole process and not transfer any files.
should have 2 date files and one info file each time.
Code:
#!/usr/bin/perl -w
use strict;
use warnings;
use Net::FTP;

# change directory
chdir "/ftp/files" or die "/ftp/files: $!\n";

# DO NOT transfer without info file
-f "/ftp/files/info" or die "info file is missing\n";

open(FILE, "<info>");
my $cwd_performed = 0;
while (<FILE> ) {
s/\W*$//;
next if (!$_);
/^(.+?) \s+ (.+?)$/x;

my ($old, $new) = ($1, $2);
rename $old, $new;

# ftp transfer
my $server = "X.X.X.X";
my $ftp = Net::FTP->new ($server, Timeout => 9000, Debug => 3);
$ftp or die "$server: cannot connect: $@";
# If you don't use ~/.netrc
$ftp->login ('anonymous', 'mail@adress') or
die "$_: cannot logon: " . $ftp->message;

# change remote directories
if ($cwd_performed >0) {
$ftp->cwd("FTP/IN2")
}
else {
$ftp->cwd("FTP/IN1") if (!$cwd_performed++)
}

# Put first file to the ftp server
$ftp->put ($2) or
die "$server: cannot put $2: " . $ftp->message;
$ftp->quit;

sleep (15 * 60)
}
 
Not sure I am understanding your question.

Are you asking 'How can I have the script check to see if the filenames are the same as the last time it ran so that it does not process duplicates?'



 
hi

yes
the exact probelm is:
I cannot send any files twice or wrong files.
this is very important.
but this script renames all files
and doesn't check if files these I get,
have the same names like in info file.

for example I get this info file :
---------------------------------
FA12300012 TN20040203
GA12300013 TT20040203
----------------------------------
and these 2 files FA12300020 GA12300022
instead of FA12300012 and GA12300013.
this script will process and send wrong files.
normally I get right files, but it could happen,
that I get wrong files.

this script will be scheduled every 5 minutes from cron job
and should wait for these 3 files and process them,
when they are correct.

kind regards
anonimous
 
If the file names are always going to be unique I would keep a dbm history of them.

So, when the cron job runs have it :

1) Open the dmb
2) Check the pre-move filename. If its in the dbm exit
3) If its not in the dbm put it there
4) close the dbm, do your magic.

 
hi

what do you mean wiht dmb ?
is it a database like mysql ?

but how to change this script to write these names
to the dbm and howto check from a cron job ?

if you can post some code it helps a lot.

greetings
anonimous
 
perldoc -f dbmopen

That will give you the docs on dbm. Its a file based hashed database structure that ships with perl and is very easy to use.

Each time you process a file you put the name in this key'd dbm database.

if you check the database BEFORE you process a file for the name you can assure yourself of uniqueness.
 
thanks for the information,
I've never used it before.

but I think, this could not solve my first problem,
because dbm doesn't know if I get wrong files or not.
I wrote an example in my second posting.
dbm can check only if files already processed or not.

this script should check first if file names
are identical as in the info file.
each time I get the info with different names.

and my question is howto change the script to do that ?

kind regards
anonimous
 
I am really not understanding you then. You said that you never want to process the same filename twice.

By putting the filename in the dbm you can later check to see if you have -ever- processed that file. If so refuse to process it.

Perhaps you can more clearly explain.
 
so I'll get 3 files from other server:
one info file and 2 data files.
each time these 2 data files will have different names,
but names of these 2 files should have the same names like
in the info file:
for example I get this info file:
---------------------------------
FA12300012 TN20040203
GA12300013 TT20040203
----------------------------------
and should get normally also 2 data files with following names:
FA12300012
GA12300013

but it could happen, I can get wrong files
with completely different names like on the info file,
or I get only one file instad of 2 files.
in both cases should not process !
so dmb doesn't know files names
and how many files I will get ( one or two ).
 
Just read the contents of your directory and check to see if the filenames match..

perldoc -f opendir

Open the directory, read the filenames in, compare them to what is in the info file and if they do not match don't process..
 
open(FILE, "<info>");
my $cwd_performed = 0;
while (<FILE> ) {
s/\W*$//;
next if (!$_);
/^(.+?) \s+ (.+?)$/x;

# check and compare files
$path = shift || "/ftp/files";

opendir(DIR, $path) or die "can't open opendir $path: $!\n;

while (defined ($fname = readdir(DIR))) {

if (


and don't get forward !
the problem is rather to compare.

can someone help me please ?
 
Here is how I would do it. I totally do not understand your selection criteria but the foreach block should let you do whatever it is you need to do.

Code:
$dir = "./" ; # Change to your file directory
$source = "./in.txt" ; # change to your source info file

open(FILE,$source)||print "Couldnt open it";
my %filehash ;
while(<FILE>){
        chop ;
        @files = split(/\W/,$_);
        $filehash{$files[0]}=$files[1];
        #print ":$files[0]:$files[1]:\n" ;
}
close(FILE);

opendir(DIR,$dir);
my @list = grep !/^\.\.?/  , readdir(DIR) ;

foreach( @list){
        # %filehash contains the text file representation where $filehash{'FA12300012' } = "TN20040203";   
        # @list is an array of all the files in this directory
        # foreach of the files ($_) check to see if its in the filehash
        # If it is you have a match, do whatever you do.
        print "Working on $_\n" ;
        print "Value in hash is ",$filehash{$_},"\n" ;
        if(exists($filehash{$_})){
            # do your ftp or rename or whatever
            `mv $filehash{$_} $_` ;
        }

}
 
hi siberian

thank you very much for your time and help !

have only problem with these 2 lines:

@files = split(/\W/,$_);
$filehash{$files[0]}=$files[1];

and get:

[Tue Mar 9 01:44:35 2004] ftp5.cgi: Global symbol "@files" requires explicit package name at ftp5.cgi line 70.
[Tue Mar 9 01:44:35 2004] ftp5.cgi: Global symbol "@files" requires explicit package name at ftp5.cgi line 71.
[Tue Mar 9 01:44:35 2004] ftp5.cgi: Global symbol "@files" requires explicit package name at ftp5.cgi line 71.
[Tue Mar 9 01:44:35 2004] ftp5.cgi: Execution of ftp5.cgi aborted due to compilation errors.

kind regards
anonimous
 
Put this at the top

my(@files, $dir,$source, %filehash, @list);

 
hi

thanks again,
but now sends wrong files (doesn't stop) and I get in the log :

[Tue Mar 9 02:08:50 2004] ftp5.cgi: "my" variable %filehash masks earlier declaration in same scope at ftp5.cgi line 68.
[Tue Mar 9 02:08:50 2004] ftp5.cgi: "my" variable @list masks earlier declaration in same scope at ftp5.cgi line 78.
[Tue Mar 9 02:08:50 2004] ftp5.cgi: Use of uninitialized value in print at ftp5.cgi line 86.
[Tue Mar 9 02:08:50 2004] ftp5.cgi: Use of uninitialized value in print at ftp5.cgi line 86.
[Tue Mar 9 02:08:50 2004] ftp5.cgi: Use of uninitialized value in print at ftp5.cgi line 86.
[Tue Mar 9 02:08:50 2004] ftp5.cgi: Use of uninitialized value in print at ftp5.cgi line 86.

for this lines:
my %filehash ; (68)
my @list = grep !/^\.\.?/ , readdir(DIR) ; (78)
print "Value in hash is ",$filehash{$_},"\n" ; (86)

the whole script looks:
Code:
#!/usr/bin/perl -w
use strict;
use warnings;
use Net::FTP;

# change directory
chdir "/ftp/files" or die "/ftp/files: $!\n";

# DO NOT transfer without info file
-f "/ftp/files/info" or die "info file is missing\n";

# check files and if do not match don't process !)
my(@files, $dir,$source, %filehash, @list);
$dir = "/ftp/files" ; # Change to your file directory
$source = "/ftp/files/info" ; # change to your source info file
open(FILE,$source)||print "Couldnt open it";
my %filehash ;
while(<FILE>){
        chop ;
        @files = split(/\W/,$_);
        $filehash{$files[0]}=$files[1];
        #print ":$files[0]:$files[1]:\n" ;
}
close(FILE);

opendir(DIR,$dir);
my @list = grep !/^\.\.?/  , readdir(DIR) ;

foreach( @list){
        # %filehash contains the text file representation where $filehash{'FA12300012' } = "TN20040203";   
        # @list is an array of all the files in this directory
        # foreach of the files ($_) check to see if its in the filehash
        # If it is you have a match, do whatever you do.
        print "Working on $_\n" ;
        print "Value in hash is ",$filehash{$_},"\n" ;
        if(exists($filehash{$_})){
            # do your ftp or rename or whatever
            `mv $filehash{$_} $_` ;
        }
}

open(FILE, "<info>");
my $cwd_performed = 0;
while (<FILE> ) {
s/\W*$//;
next if (!$_);
/^(.+?) \s+ (.+?)$/x;

my ($old, $new) = ($1, $2);
rename $old, $new;

# ftp transfer
my $server = "X.X.X.X";
my $ftp = Net::FTP->new ($server, Timeout => 9000, Debug => 3);
$ftp or die "$server: cannot connect: $@";
# If you don't use ~/.netrc
$ftp->login ('anonymous', 'mail@adress') or
die "$_: cannot logon: " . $ftp->message;

# change remote directories
if ($cwd_performed >0) {
$ftp->cwd("FTP/IN2")
}
else {
$ftp->cwd("FTP/IN1") if (!$cwd_performed++)
}

# Put first file to the ftp server
$ftp->put ($2) or
die "$server: cannot put $2: " . $ftp->message;
$ftp->quit;

sleep (15 * 60)
}
 
Only do the single 'my' declaration at the top, remove all other my declarations. Put all the variables in that declaration.

Yhave two scripts all merged together and that just does not make any sense to me at all. The idea here is that if you find a match

Code:
if(exists($filehash{$_})){
            # do your ftp or rename or whatever
            `mv $filehash{$_} $_` ;
        }

You need to put your code in that if() block.

You do your ftp for that individual file.


Your just sticking your old code on the bottom of this so the code I gave you runs properly (it never finds a match) and then my code ends and your code just does what it does which is improper.
 
hi

thanks
I am not sure if I understood you correctly,
but still get errors:

[Tue Mar 9 03:27:05 2004] ftp5.cgi: "my" variable %filehash masks earlier declaration in same scope at ftp5.cgi line 132.
[Tue Mar 9 03:27:05 2004] ftp5.cgi: "my" variable @list masks earlier declaration in same scope at ftp5.cgi line 142.
[Tue Mar 9 03:27:05 2004] ftp5.cgi: Global symbol "%filehash" requires explicit package name at ftp5.cgi line 51.
[Tue Mar 9 03:27:05 2004] ftp5.cgi: Global symbol "%filehash" requires explicit package name at ftp5.cgi line 112.
[Tue Mar 9 03:27:05 2004] ftp5.cgi: Execution of ftp5.cgi aborted due to compilation errors.

for lines:
my %filehash ; (132)
my @list = grep !/^\.\.?/ , readdir(DIR) ; (142)
if(exists($filehash{$_})){ (51)
`mv $filehash{$_} $_` ; (112)

script now:
Code:
#!/usr/bin/perl -w
use strict;
use warnings;
use Net::FTP;

my $server = "X.X.X.X";
my $cwd_performed = 0;

# change directory
chdir "/ftp/files" or die "/ftp/files: $!\n";

# DO NOT transfer without info file
-f "/ftp/files/info" or die "info file is missing\n";

if(exists($filehash{$_})){

open(FILE, "<info>");
while (<FILE> ) {
s/\W*$//;
next if (!$_);
/^(.+?) \s+ (.+?)$/x;

my ($old, $new) = ($1, $2);
rename $old, $new;

# ftp transfer

my $ftp = Net::FTP->new ($server, Timeout => 9000, Debug => 3);
$ftp or die "$server: cannot connect: $@";
# If you don't use ~/.netrc
$ftp->login ('anonymous', 'mail@adress') or
die "$_: cannot logon: " . $ftp->message;

# change remote directories
if ($cwd_performed >0) {
$ftp->cwd("FTP/IN2")
}
else {
$ftp->cwd("FTP/IN1") if (!$cwd_performed++)
}

# Put first file to the ftp server
$ftp->put ($2) or
die "$server: cannot put $2: " . $ftp->message;
$ftp->quit;

sleep (15 * 60)
}

`mv $filehash{$_} $_` ;
        }


# check files and if do not match don't process !)
my(@files, $dir,$source, %filehash, @list);
$dir = "/ftp/files" ; # Change to your file directory
$source = "/ftp/files/info" ; # change to your source info file
open(FILE,$source)||print "Couldnt open it";
my %filehash ;
while(<FILE>){
        chop ;
        @files = split(/\W/,$_);
        $filehash{$files[0]}=$files[1];
        #print ":$files[0]:$files[1]:\n" ;
}
close(FILE);

opendir(DIR,$dir);
my @list = grep !/^\.\.?/  , readdir(DIR) ;

foreach( @list){
        # %filehash contains the text file representation where $filehash{'FA12300012' } = "TN20040203";   
        # @list is an array of all the files in this directory
        # foreach of the files ($_) check to see if its in the filehash
        # If it is you have a match, do whatever you do.
        print "Working on $_\n" ;
        print "Value in hash is ",$filehash{$_},"\n" ;
        if(exists($filehash{$_})){
            # do your ftp or rename or whatever
            `mv $filehash{$_} $_` ;
        }
}
 
You now have the code all mixed up, you don't even define the variables you are using until after you use them!

Stop, breath, think and then properly set this up. You need to define the variables like %filehash before you use them etc.

I've given you the tools to accomplish this task, its up to you to use them.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top