in reply to Re: copy files
in thread Global symbol $dir requires a explicit package name ?

Dear pfaut, I've been working on this code for the past two days... do you have any suggestion on what do I need to rearrange my code to make it compile. If I rearrange my code I could get it to copy only one file but it stops there. The idea is to keep going until the end of the array and copy every file it get from the source directory to the target one. I'll appreciate your suggestions. Many Thanks

Replies are listed 'Best First'.
Re: Re: Re: copy files
by tachyon (Chancellor) on Feb 25, 2003 at 01:14 UTC

    First please learn the value of indenting you code properly so you can see the flow. If you don't know how get a copy of perltidy from sourceforge and let it do it for you till it comes naturally. Try something like this:

    #! perl -w use strict; use File::Copy; my $infile = "c:\\doclist1.chr"; my @directories; # first lets build our directory list open IN, "<$infile" or die "Couldn't open $infile, $!"; while (<IN>) { chomp; my @fields = split /,/; my $path_str = $fields[6]; do { warn "Empty field 7"; next } unless $path_str; my @path = split /\\/, $path_str; # push the directories into an array push @directories, join "\\", @path[ 0, 5, 6 ]; } close IN; # now we have a directory list in @directories let's process it for my $dir ( @directories ) { process_dir($dir); } exit; sub process_dir { my $dir = shift; do { warn "$dir does not exist!\n"; return } unless -e $dir; opendir DIR, $dir or do { warn "Could not open $dir $!\n" ; return + }; while ( my $file = readdir DIR ) { next unless -f "$dir\\$file"; next unless $file =~ m/\.rtf$/; copy( "$dir\\$file", "C:\\testfiles\\$file" ) or die "Failed to copy $file: $!\n"; } }

    Once you have the basic logic working you can add in File::Find if you need to recurse a directory structure in your process dirs sub. There were a lot of problems with your code. Foremost was that you wanted to push a list of directories into @directory but were not pushing and even if you were the my declaration in the loop would erase it every loop.

    You actually don't need @directories at all a you can just call process_dirs() in your main loop like this:

    #! perl -w use strict; use File::Copy; my $infile = "c:\\doclist1.chr"; open IN, "<$infile" or die "Couldn't open $infile, $!"; while (<IN>) { chomp; my @fields = split /,/; my $path_str = $fields[6]; do { warn "Empty field 7"; next } unless $path_str; my @path = split /\\/, $path_str; my $dir = join "\\", @path[ 0, 5, 6 ]; process_dir($dir); } close IN; sub process_dir { my $dir = shift; do { warn "$dir does not exist!\n"; return } unless -e $dir; opendir DIR, $dir or do { warn "Could not open $dir $!\n" ; return + }; while ( my $file = readdir DIR ) { next unless -f "$dir\\$file"; next unless $file =~ m/\.rtf$/; copy( "$dir\\$file", "C:\\testfiles\\$file" ) or die "Failed to copy $file: $!\n"; } }

    cheers

    tachyon

    s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

      Thanks for your help!!! I didn't think of it, but each file that I'm copying to the new directory has the same name called "word1.rtf" I would need to rename each file because if not they will not copy with the same name. Have you seen anywhere or do you know of a method to rename files dynamicaly while you are copying files to another directory? I'll appreciate any suggestions. Thanks a lot

        All you need to do is

        copy( "C:\\somename", C:\\some_path\\some_other_name" )

        To generate the new names dynamically you use something like:

        # this is a test example my $name = 'doc.txt'; for ( 1 .. 10 ) { my $unique = get_unique_filename($name); $names{$unique}++; print "$unique\n"; } sub get_unique_filename { my $name = shift; $name =~ s/(\.[^\.]+)$//; my $ext = $1 ? $1 : ''; my $tries = ''; my $max_tries = 100; while ( not unique_name($name.$tries.$ext) ) { $tries++; die "Could not make a unique file name $name\n" if $tries > $m +ax_tries; } return $name.$tries.$ext; } # this tests if our name exists in the test hash # you need to test if the file exists here instead sub unique_name { my $name = shift; return defined $names{$name} ? 0 : 1; # return -e $name ? 0 : 1; }

        Without the demo code all you need is a single sub that looks like:

        sub get_unique_filename { my $name = shift; $name =~ s/(\.[^\.]+)$//; my $ext = $1 ? $1 : ''; my $tries = ''; my $max_tries = 100; while ( -e $name.$tries.$ext ) { $tries++; die "Could not make a unique file name $name\n" if $tries > $m +ax_tries; } return $name.$tries.$ext; }

        cheers

        tachyon

        s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

Re: Re: Re: copy files
by Cabrion (Friar) on Feb 25, 2003 at 01:58 UTC
    Just move the $dir declaration up a line.
    my $dir; # my goes here foreach $dir (@dir) { # my does not go here. if ($File::Find::dir ne $dir) { $File::Find::prune = 1; return 0; }
      Cabrion, I change my code a bit but I still cannot get it to work. I keeps givng me "Global Symbol $dir requires explicit package name in line 32 and 35" I'm really hitting a wall could you help??? I don't know why it keeps giving me the error. I really need to do a recursive directory search. I'll appreciate your help...
      #! perl use strict; use File::Copy; use File::Find; no warnings 'File::Find'; my $infile = "c:\\doclist1.chr"; my @directories; # first lets build our directory list open IN, "<$infile" or die "Couldn't open $infile, $!"; while (<IN>) { chomp; my @fields = split /,/; my $path_str = $fields[6]; do { warn "Empty field 7"; next } unless $path_str; my @path = split /\\/, $path_str; # push the directories into an array push @directories, join "\\", @path[ 0, 5, 6 ]; } close IN; exit; # now we have a directory list in @directories let's process it for my $dir ( @directories ) { process_directories($dir); } find(\&process_directories, $dir); sub process_directories { if ($File::Find::dir ne $dir) { $File::Find::prune = 1; return 0; } return 0 if ($_ !~ /\.rtf$/); copy($File::Find::name, "C:\\testfiles\\$_") or die "Failed to cop +y $_: $!\n"; return 1; }