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

I've got a simple perl script where I am looping thru a directory and for each file I am 1) parsing the file, and 2)moving the file elsewhere. The parsing and moving subroutines are in external files. Independently they each work, but when I call one after the other, the parse works, and the move doesn't. It also only cycles thru one file in the directory. I'm thinnking this has to do with how the first subroutine (parsing returns). I've got some code snippets below - can someone help me figure out what I'm doing wrong?

Main file:

use Parse; # my custom Parse.pm in /etc/perl/ use Moving; # my custom Moving.pm in /etc/perl ..... foreach $file (@filelist) { Parse::parse_file($file); Moving::move_file($file); .....

In Parse.pm, it parses the file - at the very end of the function I have a "return 1" to indicate success.

Somehow it is never getting to Moving.pm, so I"m thinking it must have something to do with the return from Parse.pm - ?? does anyone have any suggestions? thanks-

Replies are listed 'Best First'.
Re: return from external subroutine
by moritz (Cardinal) on Aug 23, 2007 at 15:18 UTC

    It's really hard to help you. Please clean up your markup (insert paragraphs, put code in <code>-sections, and print all of your mail file verbatim, as well as the relevant parts of Moving.

    My guess is that you are not in the directory you think you are. But I can't tell from the piece of information you gave.

Re: return from external subroutine
by starX (Chaplain) on Aug 23, 2007 at 15:27 UTC
    First, I agree with moritz's suggestion. Second, you might want to try use strict; and use warnings; The only thing more amazing than how quickly the errors they generate can help me find and fix a problem is how often I forget to use them from the outset myself.
      my bad. The code is below with the proper markings. Again, the problem seems to be with the return of Parse.pm. All Parse.pm does it take the file, go thru it, and put parts in a mysql db. This does work. Let me know if I should post more. Thanks again. Tried -w and strict - no help!

      Main file:

      use Parse; # my custom Parse.pm in /etc/perl/ <use Moving; # my custom Moving.pm in /etc/perl ..... foreach $file (@filelist) { Parse::parse_file($file); Moving::move_file($file); ... }

      Parse.pm
      package Parse; sub parse_file { $file = $_[0]; # put data in database, etc. this all works file } return 1;
      Moving.pm
      package Moving; sub move_file { $oldfile = $_[0]; # move a file, rename it, etc } return 1;
        You're really going to want to reformat the code in your original post to look like that. Also, where is the file list coming from? You've left the juicy bits of your code out of these snippits, and I'm afraid that I'm just not good enough to be able to make an intelligent guess without seeing what you're doing.

        If you are really confident that your internals are working just fine and can't post them here, might I suggest you look into using the debugger?

        At the very least I should put return 1 within the subroutine declaration. It has no place or use here outside of the {...}

        CountZero

        A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

Re: return from external subroutine
by jbert (Priest) on Aug 23, 2007 at 16:22 UTC
    At a guess:
    1. you're running on windows
    2. the first script is keeping the file open when you launch the second. (i.e. you've forgotten the close call in parse_file)
    Ordinarily, you can't delete or rename an open file under windows.

    If you can't see an obvious missed close, you can use filemon to see what files are open and you might also want to check the value of $! when the open fails.

    It might be something else since I've not read the unformatted code you've posted.

      I'm running on Ubuntu 6.10. Below are my complete (except for Parse.pm which is over 300 lines long...

      Main file -
      #! /usr/bin/perl use Parse; use Moving; use File::Copy my @filelist = (); # all filenames will go into this global array my $txt_folder = '/temp/'; &check_folders($txt_folder); foreach $file (@filelist) { print "file is $file\n"; Parse::parse_file($file); Moving::move_file($file); } sub check_folders { #iterate thru directory, this works my($dir) = @_; local (*FOLDER); # use local for filehandles my(@subfiles, $file, $specfile); opendir(FOLDER, $dir) or die "cannot open $dir"; @subfiles = readdir(FOLDER); closedir(FOLDER); foreach $file (@subfiles) { # ignore files beginning with a period next if ($file =~ m/^\./); #$specfile = $dir . ':' . $file; $specfile = $dir . $file; if (-d $specfile) { print "directory is $specfile\n"; &check_folders($specfile); # RECURSION } elsif (-f $specfile) { push(@filelist, $specfile); # # do your text line stuff here }#if }#for }#sub __END__

      Moving.pm
      package Moving; use File::Copy; sub move_file { $oldfile = $_[0]; $newlocation="/data/bst/processed/"; move($oldfile, $newlocation) or die ("Couldn't move file"); return $oldfile } return 1;

      Now relevant parts of Parse.pm
      package Parse; use File::Copy; use Cwd; use Switch; sub parse_file { use DBI; use DBD::mysql; $dsn = "DBI:mysql:test:localhost"; $dbh = DBI->connect($dsn,"root","",{RaiseError=>1}); $newlocation = "/data/processed/"; $file = $_[0]; print "file is $file\n"; open(INFILE, $file) or die ("Unable to open $file"); while ($line = <INFILE> ) { # parse the file, put stuff in db } #end while print "done parsing\n"; $dbh->disconnect(); close(INFILE); } # end function return 1;
        Since you said the Moving::move_file was never called, so chances are that you have an infinite loop in Parse::parse_file. Try to insert a few print statements to see where it hangs.

        Speaking for infinite loops: Once you've got a symbolic link from one directory to a subdirectory you script will loop.

        You could circumvent this by checking for symlinks with -l.

        And use strict and warnings - really!

        Do you get to the "done parsing" print statement from Parsing.pm? Can you save the return value of parse_file() and print it out so that you can see what it is before starting the move attempt?

        And, definitely, use strict and use warnings.