Dear all,

I need to copy a set of files every once in a while from my build env to a shared drive.
The set of files are same, names may vary but they come with same extension.

So far I am doing it manually. I wish it could be done using a script which would be
less error prone.

List of files I need to copy every time:

*.axf
*.fls
*.txt
*.err
*.dummy
*.log
*.cfg

Build evn folder where the files are generated:

HW
HW\MODEM\
HW\MODEM\OCEAN\12345.axf
HW\MODEM\OCEAN\12345.err
HW\MODEM\OCEAN\core_dump.log
HW\MODEM\OCEAN\DUMMY\ocean.fls

I need to make sure that when I copy the files, the folder structure is maintained. That is,
I need to create the base folders first, e.g, to copy core_dump.log in example above I need to
create HW\MODEM\OCEAN\ and then copy the file underneat.

Can you please help How can I do it in a script, perl or DOS?

Thanks in advance.

File::Path
File::Find
File::Copy
File::Basename

The modules will be help to complete the needs.

Comments
Good choices.

For example:

#!/usr/bin/perl
use strict;
use warnings;

use File::Find;
use File::Path qw(make_path);
use File::Basename;
use File::Copy;

my @directories_to_search = ('/home/david/Programming/data');
my @suffixes = qw(.axf .fls .txt .err .dummy .log .cfg);

find(\&wanted, @directories_to_search);

sub wanted{
    my($filename, $directories, $suffix) = fileparse($File::Find::name, @suffixes);
    if ($suffix){
        my $target_dir = "/home/david/test/$directories";
        make_path($target_dir);
        copy($File::Find::name,"$target_dir/$filename$suffix") or die "Copy failed: $!";
    }

    print "Copied$filename$suffix\n";
}

Hi David

The solution works fine with all file types (I have tried .axf .fls .txt .err .dummy .log .cfg ) except for the object file (".o").

Here is the script I used:

#!/usr/bin/perl
use strict;
use warnings;

use File::Find;
use File::Path qw(make_path);
use File::Basename;
use File::Copy;

# Target Directory
my @directories_to_search = ('HW/TARGET_PLATFORM/MODEM_DEBUG');
#my @suffixes = qw( .axf .fls .txt .cfg .log );
my @suffixes = qw(.o);


find(\&wanted, @directories_to_search);
sub wanted{
    my($filename, $directories, $suffix) = fileparse($File::Find::name, @suffixes);

    if ($suffix){
	my $target_dir = "/home/mmhuqx/test/$directories";
	make_path($target_dir);
	copy($File::Find::name,"$target_dir/$filename$suffix") or die "Copy failed: $!";
    }
    print "Copied $filename$suffix\n";
    
}

Here are the object files in my env:

:/vobs/system-build> ls HW/TARGET_PLATFORM/MODEM_DEBUG/obj/cm/
cm.o       cmc_op1.o  cmm.o      cms.o  cmc.o      cmc_op2.o  cmm_op1.o  dir.dummy

When I run the script it gives me following error:

[tcsh] boshu@rom23:/vobs/system-build/HW/TARGET_PLATFORM/MODEM_DEBUG> perl ~/recursive_copy.pl 
Copied TARGET_PLATFORM
Copied MODEM_DEBUG_1126.04
Copied project.cfg
Copied project.cfg.log
Copied dir.dummy
Copied builderr.txt
Copied XYZ9900.map
Copied XYZ9900.axf
Copied XYZ9900.txt
Copied XYZ9900.fls
Copied src
Copied platform
Copied sysprofid.h
Copied sysprofnames.h
Copied dir.dummy
Copied ali
Copied dir.dummy
Copied dr
Copied dir.dummy
Copied ds
Copied dir.dummy
Copied mi
Copied dir.dummy
Copied mn
Copied dir.dummy
Copied msap
Copied dir.dummy
Copied pb
Copied dir.dummy
Copied om
Copied dir.dummy
Copied xdr
Copied dir.dummy
Copied biph
Copied dir.dummy
Copied mtc
Copied nas
Copied dir.dummy
Copied dir.dummy
Copied ir
Copied dir.dummy
Copied mm
Copied dir.dummy
Copied nas
Copied dir.dummy
Copied ph
Copied dir.dummy
Copied psdata
Copied dir.dummy
Copy failed: Is a directory at /home/boshu/recursive_copy.pl line 22.
[SunOS][boshu_target_product_dv][CN-ENV]                                                                                                                                                                      
[tcsh] boshu@rom23:/vobs/system-build/HW/TARGET_PLATFORM/MODEM_DEBUG>

I could not figure out what causes the error. Is the file type/suffix syntax I am using wrong?

Regards
Boshu

Edited 5 Years Ago by boshu: Too long input

I don't see what causes that error. Taking a second look at the script I see that the print statement should be inside the if block because we only want to print info about the files with the desired extension, since they are the only files to be copied. Try putting the print statement before the copy statement so we can see what it is going to try to copy before the error occurs. The following may work, or at least print better information for debugging:

#!/usr/bin/perl
use strict;
use warnings;

use File::Find;
use File::Path qw(make_path);
use File::Basename;
use File::Copy;

# Target Directory
#my @directories_to_search = ('HW/TARGET_PLATFORM/MODEM_DEBUG');
my @directories_to_search = ('/home/david/Programming/data');
#my @suffixes = qw( .axf .fls .txt .cfg .log );
my @suffixes = qw(.o);


find(\&wanted, @directories_to_search);
sub wanted{
    my($filename, $directories, $suffix) = fileparse($File::Find::name, @suffixes);

    if ($suffix){
	#my $target_dir = "/home/mmhuqx/test/$directories";
        my $target_dir = "/home/david/Programming/test/$directories";
	make_path($target_dir);
        print "Try to copy $File::Find::name ... Extension is $suffix\n";
	copy($File::Find::name,"$target_dir/$filename$suffix") or die "Copy failed: $!";
        #print only if copied.
        #print "Copied $File::Find::name ... Extension is $suffix\n";
    }   
}

I found my mistake. my @suffixes = qw( .axf .fls .txt .cfg .log .o); is not quite right because each pattern is treated as a regex (regular expression) and the dot is a special regex character which needs to be 'escaped' by preceding it with a backslash in order to represent a dot character in the extension. Instead we should escape the dot in all the patterns, like this: my @suffixes = qw( \.axf \.fls \.txt \.cfg \.log \.o); Does the following script do what you want?

#!/usr/bin/perl
use strict;
use warnings;

use File::Find;
use File::Path qw(make_path);
use File::Basename;
use File::Copy;

# Target Directory
#my @directories_to_search = ('HW/TARGET_PLATFORM/MODEM_DEBUG');
my @directories_to_search = ('/home/david/Programming/data');

#my @suffixes = qw( \.axf \.fls \.txt \.cfg \.log );
my @suffixes = qw(\.o);#Backslash to escape regex special character dot ('.')

find(\&wanted, @directories_to_search);
sub wanted{
    my($filename, $directories, $suffix) = fileparse($File::Find::name, @suffixes);

    if ($suffix){
	#my $target_dir = "/home/mmhuqx/test/$directories";
        my $target_dir = "/home/david/Programming/test/$directories";
	make_path($target_dir);
        print "Try to copy $File::Find::name ... Extension is $suffix\n";
	copy($File::Find::name,"$target_dir/$filename$suffix") or die "Copy failed: $!";
        #print only if copied.
        #print "Copied $File::Find::name ... Extension is $suffix\n";
    }   
}

Hi David. This is perfect now. Working as intended!
Many thanks.

Before closing this thread as Solved I would like to ask one more thing:
Will it work also in windows env?

I haven't tested it under Windows, only Linux. However I don't see any reason why it shouldn't work just as well in a Windows environment.

This article has been dead for over six months. Start a new discussion instead.