I used local paths and coding was done on a Unix-type system (MacOS in this case), so adjust paths and separators accordingly. Optionally, use the core module File::Spec and let it worry about the path separators. I present a few versions here.
Each version adds an important check that you're not moving all your files one after the other into a single file (leaving just the contents of the last source file).
In many cases you could skip using File::Copy and just use rename but then you may have to handle some edge cases yourself that the module handles for you. I'd recommend using the module.
You definitely don't need to take a glob of all files, then in a loop glob all files ending in '.txt' again. You can use glob to get the list (in list context) of just the files you want and iterate over that. The code below does not do what you seem to expect.:
if ($file = glob(($base)."*.txt")){
# ...
}
That is assigning the first match from glob(($base)."*.txt") to $file after you've already set $file as the loop variable. So for every file that matches glob($base/"*") you're re-globbing for "$base*.txt" using a fresh iterator internal to the perl runtime and operating on that filename that's returned in scalar context. Don't do that. Just get the right list the first time and operate on each member of that list in turn.
Here's code with hard-coded paths in Unix path form to where I was working with the files.:
#!/usr/bin/perl
use strict;
use warnings;
use File::Copy ();
my $base = '/Volumes/case-sensitive/projects/monks/1190936';
my @time = (localtime)[ 5, 4, 3 ];
$time[0] += 1900;
$time[1]++;
my $dir_for_today = sprintf '%s/%04d/%02d/%02d', $base, @time;
die "destination $dir_for_today is not a directory!\n" unless -d $dir_
+for_today;
foreach my $file ( glob qq($base/*.txt) ) {
File::Copy::move $file, $dir_for_today or warn "Can't move $file
+ to $dir_for_today : $!";
}
Here's equivalent code using File::Spec to worry about the path separator. :
#!/usr/bin/perl
use strict;
use warnings;
use File::Copy ();
use File::Spec;
my $volume = ''; # empty string for Unix
my @dirs = ( File::Spec->rootdir, 'Volumes', 'case-sensitive', 'projec
+ts', 'monks', '1190936' );
my $base = File::Spec->catpath( $volume, File::Spec->catdir( @dirs ),
+'' );
my @time = (localtime)[ 5, 4, 3 ];
$time[0] += 1900;
$time[1]++;
$time[1] = sprintf '%02d', $time[1];
$time[2] = sprintf '%02d', $time[2];
my $dir_for_today = File::Spec->catdir( $base, @time );
die "destination $dir_for_today is not a directory!\n" unless -d $dir_
+for_today;
foreach my $file ( glob File::Spec->catfile( $base, '*.txt' ) ) {
File::Copy::move $file, $dir_for_today or warn "Can't move $file
+ to $dir_for_today : $!";
}
For your path, according to your example I think you'd want 'D' for your volume, and of course you'd want 'Some', 'specific', 'folder' in your @dirs array according to your example.
A couple more are below...
So yeah, there are plenty of ways to accomplish this. This is but a pittance. Someone from here might suggest a modulino. Someone else may criticize using accessors in the OO version. Someone might suggest leaving the loop from the move method in the calling program. Software is flexible, programming languages are more so, and Perl more so than many programming languages. I hesitate to show it here, but this could also be done handily in a Perl (or Bash, or probably PowerShell) one-liner.
|