tags:

views:

106

answers:

3

Hello all, this morning, my friend and I discussed and wrote the below code. The idea behind this Perl script is to create the directory structure and copy the files to the corresponding directory.

#!/usr/bin/perl
use File::Path;
use File::Copy;
use Path::Class;
use File::Basename qw/dirname/;
my $src = "/Vijay/new.txt";
unless (open(MYFILE, "file1")) {
    die ("cannot open input file file1\n");
}
$line = <MYFILE>;
while ($line ne "") {
    print ($line);
    mkdir_and_copy($src,$line);
    $line = <MYFILE>;
}
sub mkdir_and_copy {
    my ($from, $to) = @_;
    my($directory, $filename) = $to =~ m/(.*\/)(.*)$/;
    print("creating dir $directory");
    system "mkdir -p $directory";
    print("copying file $from to $to");
    system "cp -f $from $to";
    return;
}

The above piece of code creates the directory structure, but fails to copy the files to the corresponding directory. Could you please let us know, where exactly we are wrong?

Contents of file1:

test/test1/test2/test.txt

Contents of new.txt:

Shell/Test/test1/test1.txt
Shell/Test/test2/test2.txt
Shell/Test/test3/test3.txt

Output:

> ./mypgm.pl
test/test1/test2/test.txt
creating dir test/test1/test2/copying file /Vijay/new.txt to     test/test1/test2/test.txt
cp: cannot access /Vijay/new.txt: No such file or directory
>

The directory Vijay has the file new.txt with the above mentioned content.

Thanks in advance,

Vijay


Hello everyone,
I just modified my code. Please refer the below section of code.

#!/usr/bin/perl        
use File::Path;    
use File::Copy;    
use File::Basename qw/dirname/;    

my $src = "./Vijay/new.txt";       
unless (open(MYFILE, "file1"))    
{    
die ("cannot open input file file1\n");    
}

$line = ;
while ($line ne "")
{
print ($line); print("\n");
mkdir_and_copy($src,$line);
$line = ""; }

sub mkdir_and_copy        
{      
my ($from, $to) = @_;    
my($directory, $filename) = $to =~ m/(.\/)(.)$/;    
$temp = $directory.$filename;    
print("Creating dirrectory $directory \n");    
if(! -d $directory)    
{    
mkpath($directory) #or die "Failed to create path";    
}    
printf("From: $from \n");    
printf("To: $temp \n");    
copy($from,$temp) or die "Failed to Copy";    
return;    
}    

Now, it creates the exact directory structure and copies the file to the corresponding directory. Could you please tell me that, whether the above code is a proper one?

A: 

The first thing to do if something "does't work" is to catch errors and to look at them. Then to investigate content of variables. In your case the variable $to just contains the file name, so the script copies it into the current working directory, I'd imagine, not into the newly created directory.

HOWEVER, the methods you're using to get your job done are not exactly the best. It would be better to actually use File::Path and File::Copy, and in particular your way of splitting a path into directory and filename at the first slash is anything but general. This sort of thing should be done in libraries, of which Perl has many.

chryss
Fine. What exactly I should do to make the script to copy the files to the corresponding directories? Could you please be specific? I tried with Shell Scripting, and it does work. I do not understand, why the same kinda login doesn't work with Perl!
Invincible
A: 

Your goal is not clear to me, but perhaps this will help you solve the problem:

# Perl scripts should always include this.
# Your original script was generating some useful warnings.
use strict;
use warnings;

my $src = "/Vijay/new.txt";
my $f1  = 'file1';

# This is the recommended way to open a file --
# that is, using a lexical file handle.
open(my $file_handle, '<', $f1) or die "open() failed : $f1 : $!";

# This is the typical way of iterating over the lines in a file.
while (my $line = <$file_handle>){
    # You probably want to remove the newline
    # before passing the line to mkdir_and_copy()
    chomp $line;

    mkdir_and_copy($src, $line);
}

sub mkdir_and_copy {
    my ($from, $to) = @_;
    my ($directory, $filename) = $to =~ m/(.*\/)(.*)$/;

    # When writing a script that makes system() calls,
    # start by simply printing them. After everything
    # looks good, convert the print commands to system() calls.
    print "system(): mkdir -p $directory", "\n";
    print "system(): cp -f $from $to",     "\n";

    # The return is not needed.
}

When I run the script with the inputs you provided, here's the output:

system(): mkdir -p test/test1/test2/
system(): cp -f /Vijay/new.txt test/test1/test2/test.txt

This can't be your intent. In particular, why are you iterating over file1 when it contains only one line? Perhaps you meant to iterate over new.txt?

FM
Yes, you are right, FM. Actually, I should iterate new.txt.Because it has the directory structure that needs to be created. I'm totally confused now. Could you please make it a bit more clear to me?My questions are, the new.txt file has the directory structure that needs to be created. Then, why am I iterating file1?
Invincible
A: 

I'll bet your $line variable still has a newline appended to it. The input returned from the filehandle input operator (<MYFILE>) includes the record separator (usually the newline character(s) for your OS). Try this:

$line = <MYFILE>;
chomp($line);
mobrule