• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 429
  • Last Modified:

copying files using perl/unix

Hi,
 I want to copy a file from source to destination by matching the directory names.

Example:   Batch0001  is the higher level directory and 4567890R is the sub directory which consists of several  log files.
Source:                                                                                                                  
Batch0001 -> 4567890R
                 ->  1237896R
                 ->   4561089R
Batch0002  ->  ....
......


Destination:
Batch0001 -> 4567890R
                 ->  1237896R
                 ->   4561089R
Batch0002  ->  ....
......

My source and destination will have the same directory structure and filenames. So it has to compare them and when it encounters same  directory and sub directory it has to copy from  source to des a file by name :  4567890R(subdirectory name)_nornalize.log
0
new_perl_user
Asked:
new_perl_user
  • 3
  • 2
  • 2
2 Solutions
 
Martin_J_ParkerCommented:
If you just want to copy all of the *_normalize.log files across from /source to /dest on Linux and the directory structures already match between /source and /dest then all you should need to do is:

cd /source
find  .  -name  '*_normalize.log'  -exec  cp  {}  /dest/{}  ';'

and if you want it to list the files as it is copying use:

cd /source
find  .  -name  '*_normalize.log'  -exec  cp  {}  /dest/{}  ';'  -print
0
 
wilcoxonCommented:
What if the destination directory doesn't exist?  Should it be created or should those files not be copied?

Change the variable values where indicated in the comments and this should do what you want.  If it doesn't work, let me know what is wrong and I'll fix it.
#!/usr/local/bin/perl

use strict;
use warnings;
use File::Copy qw(cp);
use File::Find;
use File::Path;

use vars qw/*name *dir *prune/;
*name   = *File::Find::name;
*dir    = *File::Find::dir;
*prune  = *File::Find::prune;

# change these to the real source and destination root folders
my $src_dir = '/src';
my $dest_dir = '/dest';

# change this to 1 if you want to make the dest dir if it does not exist
# 0 will skip the file if the dest dir does not exist
my $mk_dest = 0;

use Cwd ();
my $cwd = Cwd::cwd();

# Traverse desired filesystems
File::Find::find({wanted => \&wanted}, $src);
exit;

sub wanted {
    return unless /^_normalize.log$/;
    my $file = $_;
    my $dpath = $dir;
    # remove $src_dir from the dir
    $dpath =~ s{^$src_dir}{$dest_dir};
    if ($mk_dest) {
        make_path($dpath) unless (-d $dpath);
    } else {
        return unless (-d $dpath);
    }
    cp $name, "$dpath/$file" or die "could not copy $name: $!";
}

Open in new window

0
 
Martin_J_ParkerCommented:
If the destination directory does not exist you can still do something similar with a simple bash script
- just change /source and /dest to the source and destination directory names:

#!/bin/bash
#
#Start in the source directory
cd /source
#
#Find all the normalize.log files:
for i in `find . -name *_normalize.log`; do
#
# For each file find what it's directory name is relative to /source
   j=`dirname $i`
#
# If the directory does not exist in /dest then create it
   if [ ! -d /dest/$j ]
   then
      mkdir /dest/$j
   fi
#
#Copy the file over to /dest
   cp $i /dest/$i    
done
#
#End of bash script

You can make the script executable with the command
chmod 755 scriptname
0
Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

 
point_pleasantCommented:
Very simple one liner that will create the directories as needed.  If you need the original dates of the files use the -m option with cpio

find /source -name *_normalize.log -depth | cpio -pmdv /dest
0
 
wilcoxonCommented:
If his system has cpio (most but not all do).

Also, won't that command copy the files to /dest/src/path/*_normalize.log (rather than /dest/path/*_normalize.log)?
0
 
wilcoxonCommented:
One minor tweak to my code - line 30 should be:

return unless /_normalize.log$/;

Otherwise, it will only look for files named (exactly) _normalize.log.
0
 
point_pleasantCommented:
possibly depends on the version, but if it does simply cd into source directory first then execute.

find . -name *_normalize.log -depth | cpio -pmdv /dest
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

  • 3
  • 2
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now