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

Hi Monks, Am in a stuck up in a complex problem and being a newbie not able to solve it .. I have list of filenames without there full path in an perl array extracted from database based on Start and End Date. I have 3 directories Work,Archive,Error. I need to Check my Archive directory if there is a directory like FirstDate_LastDate with all the files which are present in my array than I need to copy them to work directory and ftp them ( I have a ftp function) .. after that remove them from work directory coz they were present in archive. If the archive dir does not contain a directory of type FirstDate_LastDate, I need to search the filename in another directory tree for each of filename present in array.If file is found in another dir (This is a directory tree with many sub directories containing diff files), I need to copy it to work dir and search for second file .. until my array gets over. Any help on this will be valuable ... Regards, Perl Wisdom Seeker - Sumit

Replies are listed 'Best First'.
Re: Find Filename in Directory Tree and copy to another directory ..
by spazm (Monk) on Jul 08, 2009 at 22:52 UTC
    To reformat your problem:

    You have:

    • A list of filenames without their full path in an perl array extracted from database based on Start and End Date.
    • start_date
    • end_date
    • three directories Work,Archive,Error.
    • working ftp function
    • another directory tree somewhere.
    Given these items, you wish to take these actions:
    • Check archive directory for a directory named "FirstDate_LastDate" with all the files which are present in my array.
      If found:
      1. copy them to work directory
      2. ftp them somewhere ( I have a ftp function).
      3. Then remove them from work directory since they were present in archive.

      If not found:
        search the filename in another directory tree for each filename present in array.
      1. if found, copy it to work dir and search for next file
      2. continue until array gets over.
      open questions:
      1. What is the error directory for?
      2. Where is the "another directory tree"?
      3. Should files found in "another directory tree" be pushed with FTP like the archive ones?
      4. what happens if the archive/startDate_endDate/ directory exists, but doesn't contain all the files in your list?
      5. what happens if the "another directory tree" contains some, but not all, of the files in our list?

      The details of the script won't be very hard, once you answer the missing questions in your specification.

      You'll find File::Find helpful, along with the '-e' check for file existence and the '-d' check for directory existense.

      #!/usr/bin/perl use strict; use warnings; use File::Find; use File::Copy; my %dir = ( archive => '/path/to/archive', work => '/path/to/work', error => '/path/to/error', another => '/path/to/another', ); my $startDate = 'Jan1'; my $endDate = 'Jan31'; my @list_of_filenames = qw( a b c d other ); my $archive_target = $startDate . '_' . $endDate; do_stuff_on_my_array($archive_target, \@list_of_filenames); sub do_stuff_on_my_array { my ($archive_target, $aref) = @_; my $found_all = 1; foreach my $file (@$aref) { $found_all=0 unless check_if_file_exists_in_dir( $file, $dir{'archive'} . '/' +. $archive_target); } if( $found_all ) { foreach my $file (@$aref) { my $orig = $dir{'archive'} . '/' . $file; my $target = $dir{'work'} . '/' . $file; cp( $orig, $target ); ### my_ftp( $target ); unlink $target; } } else { my $found_path_for_file = search_for_files_in_dir( $dir{'anoth +er'}, $aref); #what do we do with these files we found? FILE: foreach my $file (@$aref) { my $fullpath = $found_path_for_file->{$file} ; unless( $fullpath) { warn "file was not found[$file]"; next FILE; } cp ($fullpath, $dir{'work'}); } } } sub check_if_file_exists_in_dir { my( $file, $dir ) = @_; return ( -d $dir && -e "$file/$dir") ? 1 : 0 ; } sub search_for_files_in_dir { my($dir, $aref)=@_; my $files = map{ $_ => 1} @$aref; my $file_path; # build a hash with the names I'm looking for my $wanted = sub { if ( exists $files->{$_} ) { $file_path->{ $_ } = $File::Find::name ; return 1; } else { return 0; } }; if ( %{$file_path} != %{$files} ) { warn("some files could not be found!"); } return $file_path; }
Re: Find Filename in Directory Tree and copy to another directory ..
by ww (Archbishop) on Jul 08, 2009 at 22:23 UTC
    First, sit down with a stubby pencil and a sheet of paper. Work out the steps you'd need to take and the criteria by which you'll decide which step to take for any given instance of your data or, at least, for a representative sample of the data.

    Then turn the result into pseudo-code -- or directly to code if you have the required knowledge and skills.

    When you run into problems with particular pieces of the code you're trying to produce, try Tutorials, Super Search, the CB and if all that fails, post your question showing what you've done along with a clear explanation of what's happening that you didn't expect or not happening that you did expect.

    Add a small sample of output, error messages and warnings, and -- of course -- a small sample of your data (enclosed in <code>...</code> tags). For more on formatting (your question above would surely be easier to read were it divided into several paragraphs or structured as a list), see Markup in the Monastery.

    Actually, of course, since you didn't just get here yesterday, you probably know most of this but on the other hand, it appears to be your first post, so perhaps some or all the above will be useful.

Re: Find Filename in Directory Tree and copy to another directory ..
by mhearse (Chaplain) on Jul 08, 2009 at 22:23 UTC
    My suggestion would be to use File::Find. Rather than copying and deleting files, I would suggest using the symlink function (perldoc -f symlink). This would be simpler and improve speed.