Lisa
Lisa

Reputation: 959

How to move files from a server to the computer using perl

I want to move files from a server that my Windows computer is connected to, to the actual computer. I have tried the code on my mac and it works fine, so I suspect the problem has to do with the fact that the files I wish to move are on a server or perhaps with Windows (I am unfamiliar with this OS). It is important to me to be able to use File::Find::Rule because there are many subdirectories within subdirectories that need to be searched.

use strict;
use warnings;
use File::Find::Rule;
use File::Copy;

# directory where files live
# my $dir = "\\172.18\user\folder\folder2";

# directory where TextGrids will be moved to
my $outdir = "\users\lisa\desktop\test";

my @files;

@files = File::Find::Rule   -> file()
                             -> name("*_clean.TextGrid")
                             -> maxdepth()
                             -> in($dir);

foreach my $file (@files) {
    $file =~ /(.*\\)(.*)/;
    my $name = $2;
    copy("$file", "$outdir/$name") or die "Copy failed: $!";
    }

Edit: Ok, I've made some changes to the script below. But the strange thing is, that when I ask it to print each file, it gives me something like \\172.18\user\folder\folder/255/file.txt. I changed the regex to be (.*\/)(.*) and now the script works perfectly, though I don't know why!

use strict;
use warnings;
use File::Find::Rule;
use File::Copy;

# directory where files live
my $dir = "\\\\172.18\\user\\folder\\folder2";

# directory where TextGrids will be moved to
my $outdir = "C:\\Users\\lisa\\desktop\\test";

my @files;

@files = File::Find::Rule   -> file()
                             -> name("*_clean.TextGrid")
                             -> maxdepth()
                             -> in($dir);

foreach my $file (@files) {
    print "$file\n";
    $file =~ /(.*\\)(.*)/;
    my $name = $2;
    copy("$file", "$outdir\\$name") or die "Copy failed: $!";
    }

Upvotes: 1

Views: 177

Answers (2)

Silvar
Silvar

Reputation: 705

After your edit, the script works because the last directory separator in the string happens to be /, which is matched by the \/ in the regular expression. Even though you had \ in the input, the library you used to find the files added /s.


I have some suggestions:

  1. You can avoid the need to escape (most) backslashes by using single quoted strings, unless you need the interpolation of the double quoted ones.

    Escaping backslashes is optional unless followed by a single quote or another backslash:

    my $outdir = '\users\lisa\desktop\test';
    

    but

    my $outdir = '\users\lisa\desktop\test\\';
    $outdir = '\users\lisa\desktop\test\\\'ere is a path';
    
    my $not_a_path = 'three backslashes\\\\\in between, all but the last need escaping';
    

    'ere is a path is the last element in that path.

  2. If you're dealing with Windows, consider using [\\/] in place of directory separator in regular expressions. (Or [\\\/] if you absolutely must use / as regular expression delimiter.)

    Even if you have control over user input to only use \ in paths, libraries you use will usually add /, so it's better to be prepared for a combination of both.

    $file =~ /(.*[\\\/])(.*)/;
    $file =~ m{(.*[\\/])(.*)};
    $file =~ m¤(.*[\\/])(.*)¤;
    

I also removed the superfluous quotes from around $file in the copy() call. Final result:

use strict;
use warnings;
use File::Find::Rule;
use File::Copy;

# directory where files live
my $dir = '\\172.18\user\folder\folder2';

# directory where TextGrids will be moved to
my $outdir = 'C:\Users\lisa\desktop\test';

my @files;

@files = File::Find::Rule   -> file()
                            -> name("*_clean.TextGrid")
                            -> maxdepth()
                            -> in($dir);

foreach my $file (@files) {
    print "$file\n";
    $file =~ /(.*[\\\/])(.*)/;
    my $name = $2;
    copy($file, "$outdir\\$name") or die "Copy failed: $!";
}

Upvotes: 1

ikegami
ikegami

Reputation: 385506

use strict;
use warnings;

my $dir = "\\172.18\user\folder\folder2";
print("$dir\n");

my $outdir = "\users\lisa\desktop\test";
print("$outdir\n");

outputs

Unrecognized escape \d passed through at a.pl line 7.
\172.18Ser?older?older2
Sersisadesktop  est

You need to escape your backslashes!

use strict;
use warnings;

my $dir = "\\\\172.18\\user\\folder\\folder2";
print("$dir\n");

my $outdir = "\\users\\lisa\\desktop\\test";
print("$outdir\n");

Don't ignore warnings.

Upvotes: 0

Related Questions