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

I need help debuging this code. I received a variable call $fixed_path. this path containes a directories and subdirectory which I search for a RTF file. It is not working now. for example H:\08\00004D04.009 Is there any way that anyone could take a look at the code and let me know what is missing to make it work??
use File::Find; use File::Copy; sub find_copy_rename { my @dir = $fixed_path; my @get_directory = substr($fixed_path,-12); my $get_each_directory = @get_directory; my $dir = @dir; my $current_path = 'C:\\temp\\'; if ($File::Find::dir ne $dir) { $File::Find::prune = 1; return 0; } return 0 if ($_ !~ /\.rtf$/); copy($File::Find::name, $current_path.$_) or die "Failed to copy $ +_: $!\n"; return 1; } find(\&process_files, $dir); my @process_file = &process_files; my $get_files = grep { !-d } @process_file; foreach my $get_files (@process_file) { my $newfile = $get_files; $newfile =~ s/\$mrn.$get_each_directory.'.'.rtf$/word1.rtf/; if (-e $newfile) { warn "can't rename $get_files to $newfile: $newfile exists\n"; } elsif (rename "$newdir/$get_files", "$newdir/$newfile") { print "file was renamed to $newfile\n" } else { warn "rename $get_files to $newfile failed: $!\n"; } }

Replies are listed 'Best First'.
Re: Find, copy & rename
by blokhead (Monsignor) on Feb 24, 2003 at 05:20 UTC
    "Not working" is pretty vague -- can you narrow it down? Does it not find the appropriate files? Does it find them but not rename them properly? I see some variables that are undeclared ($get_each_directory, $mrn).. is this all your code? A few things I noticed off the bat though:         my $current_path = 'C:\\temp\\'; Either escape your backslashes or use single quotes, but not both.
    my $get_files = grep { !-d } @process_file; foreach my $get_files (@process_file) {
    Do you mean to iterate through each of the non-directories? Then you probably meant foreach my $get_files (grep { !-d } @process_file)

            } elsif (rename "$newdir/$get_files", "$newdir/$newfile") { I'm not a win32 Perl user, but I'm not convinced using forward slashes will work here.

    Also, I'm not sure what's the reasoning with the assignments from scalar to array and back to scalar again at the top of your code.

    blokhead

      Blokhead, The problems I'm having is passing $fixed_path to sub routine (sub find_copy_rename) my code works independantly but now I'm trying to make it work dynamicall by reading a file and getting values out of the file like a file path , certain numbers , etc. I tried to compile it but it gives me $dir, $get_each_directory & $newdir "requires a special package name" I'll appreciate your help.

        The documentation of File::Find says:

        WARNINGS

        If you run your program with the -w switch, or if you use the warnings pragma, File::Find will report warnings for several weird situations. You can disable these warnings by putting the statement

            no warnings 'File::Find';
        

        in the appropriate scope. See perllexwarn for more info about lexical warnings.

        Perhaps that is the "cause" of your weird error messages.

        CountZero

        "If you have four groups working on a compiler, you'll get a 4-pass compiler." - Conway's Law

Re: Find, copy & rename
by CountZero (Bishop) on Feb 24, 2003 at 07:31 UTC

    The canonical way of passing parameters to a sub-routine is by using the @_ array and shifting the value of the parameter(s) into whatever variable(s) you use inside the sub-routine (preferably a variable declared with my).

    I think there are lots of other things wrong (or at least, strange) with your sub-routine, but perhaps you first solve the parameter passing issue and then we look at the rest.

    CountZero

    "If you have four groups working on a compiler, you'll get a 4-pass compiler." - Conway's Law

Re: Find, copy & rename
by Thelonius (Priest) on Feb 24, 2003 at 15:00 UTC
    We've drawn lots and I came up with the short stick. It's my duty to tell you that nearly every line of your program is wrong. (I'm reminded of what Mary McCarthy said about Lillian Hellman's writing.)
    use File::Find; use File::Copy; sub find_copy_rename { # THIS FUNCTION IS NOT THE ONE CALLED BELOW # WHY IS IT HERE? my @dir = $fixed_path; # HERE YOU ARE ASSIGNING A SCALAR TO AN ARRAY # It will work, but why are you doing it? my @get_directory = substr($fixed_path,-12); # HERE YOU ARE ASSIGNING A SCALAR TO AN ARRAY # It will work, but why are you doing it? # Why are you using the last 12 characters of $fixed_path? # How do you know that is what you want? my $get_each_directory = @get_directory; # HERE YOU ARE ASSIGNING AN ARRAY TO A SCALAR # AFTER THIS '$get_each_directory' WILL EQUAL THE NUMBER 1 my $dir = @dir; # HERE YOU ARE ASSIGNING AN ARRAY TO A SCALAR # AFTER THIS '$dir' WILL EQUAL THE NUMBER 1 # PROBABLY THIS IS NOT WHAT YOU WANT my $current_path = 'C:\\temp\\'; # HERE $dir == 1, so this will always FAIL if ($File::Find::dir ne $dir) { $File::Find::prune = 1; return 0; } # IT LOOKS LIKE YOU WANT TO ONLY LOOK IN THE DIRECTORY # ASSOCIATED WITH $fixed_path. IF SO, CONSIDER USING # readdir() or glob() RATHER THAN File::Find return 0 if ($_ !~ /\.rtf$/); copy($File::Find::name, $current_path.$_) or die "Failed to copy $ +_: $!\n"; return 1; } find(\&process_files, $dir); # WHERE IS THIS FUNCTION 'process_files'? my @process_file = &process_files; # NOW YOU ARE CALLING 'process_files' AGAIN. # ALMOST CERTAINLY WRONG # Functions used in File::Find do not return a list of files # You can append to a list in the function called from # File::Find my $get_files = grep { !-d } @process_file; # NO, THIS IS WRONG # HERE 'get_files' IS SET TO THE _number_ OF NON-DIRECTORY # FILES IN THE ARRAY @process_file foreach my $get_files (@process_file) { my $newfile = $get_files; $newfile =~ s/\$mrn.$get_each_directory.'.'.rtf$/word1.rtf/; # THE VARIABLE '$get_each_directory' IS NOT IN SCOPE HERE # (AT LEAST IN THE CODE WE SEE) # THE LEFT-HAND SIDE OF YOUR SUBSTITUTION MAKES NO SENSE # IT IS ALREADY QUOTED SO YOUR USE OF ' and . IS ERRONEOUS if (-e $newfile) { # YOU (MAY) NEED TO INCLUDE A DIRECTORY HERE # UNLESS $newfile INCLUDES A DIRECTORY OR YOU # ARE LOOKING FOR IT IN THE CURRENT DIRECTORY warn "can't rename $get_files to $newfile: $newfile exists\n"; } elsif (rename "$newdir/$get_files", "$newdir/$newfile") { # WHAT IS '$newdir' ???? print "file was renamed to $newfile\n" } else { warn "rename $get_files to $newfile failed: $!\n"; } }
    If you want make a list of all the files with names ending in '.rtf' in a particular directory (name already in $dir):
    my @rtf_in_dir = glob("$dir/*.rtf");
    Note that the elements of this array include the directory name. If you want to search subdirectories, too, then you should use File::Find:
    use File::Find; my @rtf_in_subddirs; sub wanted { if (/\.rtf$/) { push @rtf_in_subdirs, $File::Find::name; } } find(\&wanted, $dir);