adriang has asked for the wisdom of the Perl Monks concerning the following question:
Hi All,
How can I copy/move dir with space.
The Below code does not work.
opendir(my $dir, "/pr/perl_by_example") or die;
opendir(my $dir2, "/pr/book") or die;
while (my $file=readdir($dir)) {
next if $file =~ /\./;
copy("/pr/perl_by_example/$file", "/pr/book/") or die;
}
Here are the dirs:
/pr/perl_by_example/Chapter 03
/pr/perl_by_example/Chapter 04
/pr/perl_by_example/Chapter 05
/pr/perl_by_example/Chapter 06
/pr/perl_by_example/Chapter 07
/pr/perl_by_example/Chapter 08
/pr/perl_by_example/Chapter 09
/pr/perl_by_example/Chapter 10
/pr/perl_by_example/Chapter 11
/pr/perl_by_example/Chapter 12
/pr/perl_by_example/Chapter 13
/pr/perl_by_example/Chapter 14
/pr/perl_by_example/Chapter 15
/pr/perl_by_example/Chapter 16
/pr/perl_by_example/Chapter 17
/pr/perl_by_example/Chapter 18
/pr/perl_by_example/Chapter 19
/pr/perl_by_example/Chapter 20
Thanks in advance
Re: Copy dir with space
by Discipulus (Canon) on Jul 10, 2014 at 08:48 UTC
|
| [reply] [d/l] |
Re: Copy dir with space
by Don Coyote (Hermit) on Jul 10, 2014 at 09:29 UTC
|
Hi adriang,
I contend there are several issues here, least of which is the filename containing a space.
Firstly, use strict and warnings, if you did already, pls include with code example to show this. Secondly, copy, afaik is not a perl built-in (perldoc -f copy = not found).
copy is a utility function which can be found in another module similar to File::Spec, I cannot recall which this moment. So basically, opendir to copy files from, readdir, filter, read contents into filehandle, open new filehandle name in destination directory, print contents.
Untested! But, principally something like this, if the 'copy' containing module cannot be used.
use strict;
use warnings;
use File::Spec::Functions qw/catfile/;
my $dirnameto = catfile(qq{pr book});
my $dirnamefrom = catfile(qq{pr perl_by_example});
opendir( $dhandlefrom, $dirnamefrom )or die;
while (my $file=readdir($dirhandlefrom)) {
next if $file =~ /\./;
my $filecontents;
{local $/ = undef; # slurp mode;
open( my $tfh, '<', catfile( qq{$dirnamefrom $file} ) ) or die;
$filecontents = <$tfh>;
close $tfh; # for clarity;
}
open( my $filecopy, '>', catfile( qq{$dirnameto $file} )) or die;
+
print { $filecopy } $filecontents;
close $filecopy;
}
DC | [reply] [d/l] |
|
| [reply] |
|
not quite. Couple of straight forward syntax errors. Catfile is probably fine, as the program died at an expected line, and, has compiled without complaining about the existence of the function catfile. But the arguments passed to it are amiss. This is probably due to the paths not being stated relatively in the rough draught.
There was a thirdly, I did not mention previously. Thirdly, Paths and Files are different entities. You are using two directory opens when that is not needed for this copy operation. I think you may need to review the difference between a path and a file. To further complicate this issue, a Directory is a File. Well it is easier to say that both a directory and a file can be recognised as a string (or path). You then need to treat that string correctly depending whether it is a file, or a directory.
P.S. That is what untested means, 'probably does not work, but you get the gist...'
hope this helps. DoC
| [reply] |
Re: Copy dir with space
by duelafn (Parson) on Jul 10, 2014 at 12:04 UTC
|
Generally files with spaces are no problem as long as you are not using the shell. You didn't include your code for the copy function, but if it works on directories without spaces, I expect it uses the cp shell command (which can be dangerous depending on how it is used and exactly how it is implemented).
The code below will be safe as it never passes the file names to the shell.
#!/usr/bin/perl
use strict; use warnings;
use Path::Class;
use File::Copy::Recursive qw/ dircopy /;
my $source = "/pr/perl_by_example";
my $dest = "/pr/book";
for my $path (dir($source)->children) {
next if $path =~ /\./;
my $target = dir($dest, $path->basename);
dircopy $path, $target or die "Error copying $path: $!";
}
dir($source)->children will not include the '.' and '..' special directories, but will include everything else (including hidden files and directories). Thus, I left your $path =~ /\./ test in place. However, that test looks suspicious since it will match a '.' anywhere in the name (beginning, middle, end) so will usually match file names as well (but not always, since not all file names have an extension). To exclude hidden files and directories use: next if $path =~ /^\./; To exclude all files and only copy directories next unless $path->is_dir; If you want to exclude both (all hidden files and directories as well as all file), I would suggest including both tests separately:
for my $path (dir($source)->children) {
next if $path =~ /^\./; # exclude hidden files and directories
next unless $path->is_dir; # exclude files
my $target = dir($dest, $path->basename);
dircopy $path, $target or die "Error copying $path: $!";
}
| [reply] [d/l] [select] |
|
| [reply] |
Re: Copy dir with space (Path::Tiny)
by Anonymous Monk on Jul 10, 2014 at 09:19 UTC
|
The Below code does not work. Yes, it doesn't compile for me either :) This does compile
#!/usr/bin/perl --
use strict;
use warnings;
use Path::Tiny qw/ path cwd /;
my @files = grep { -f $_ } path( '/pr/perl_by_example/' )->children();
for my $source ( @files ) {
my $destination = path( "/pr/book/", $source->basename );
$source->copy( $destination );
}
| [reply] [d/l] |
|
| [reply] |
|
| [reply] |
|
well, then you got no files
| [reply] |
|
|
|
|
|