I don't want to have to download anything additional to run my program (for the find rule).
I'm not sure that I understand your reluctance to install additional modules. One of the strengths of Perl is leveraging the modules available at CPAN. To install File::Find::Rule, you just need to type cpan -i File::Find::Rule. But if you're insisting on not installing additional modules, I won't pressure you to do what you don't want to do.
Instead, would you have an idea of how to improve my program with what I have right here and my current set of skills?
Unfortunately you really haven't provided enough details. I don't know what kind of files that you have that you're trying to copy/move and you're not really providing enough details about what copied and what didn't. Without more information, I'd have to agree with aaron_baugher's suggestions (Re: Perl - Copy files to a newly created folder) as a good starting point for debugging your script.
I really appreciate your help but I need something less complicated.
Other than possibly learning a new module, I really don't think that the code in my last post was really complicated. In fact, I personally think that trying to use opendir/readdir/closedir is actually a bit more complicated than using File::Find::Rule since you now have to do more work.
Here's a modification of my previous code using only core modules and using opendir/readdir/closedir in place of File::Find::Rule.
use strict;
use warnings;
use feature 'say';
use File::Copy;
use File::Spec::Functions;
use File::Path qw(make_path);
use Cwd;
# getting the "source" directory
my $pwd = cwd();
my $source_dir = catdir($pwd,'source');
my @files;
opendir(my $dir,$source_dir) or die "Unable to open directory '$source
+_dir': $!";
# search for files in the specified directory
while (my $item = readdir($dir)) {
# skip . and ..
next if ($item =~ m/^\./);
# skip directories
next if (-d $item);
# if this is a file, add it to the @files array
my $test = catfile($source_dir,$item);
if (-f $test) {push @files,($item);}
}
closedir($dir);
# process the files found
foreach my $file (@files) {
# get the file's extension
my ($extension) = ($file =~ m/.+\.(.+)/);
my $subdir = catdir($source_dir,$extension);
# if the folder for the extension does not exist, create it
if (!(-d $subdir)) {make_path($subdir);}
my $source = catfile($source_dir,$file);
my $target = catfile($subdir,$file);
# copy the file to the appropriate folder
copy($source,$subdir);
# move the file to the appropriate folder
#move($source,$target);
}
In this version, I'm using a while loop to process through the contents of the directory. In that loop, I'm needing to be aware of and handle the special cases of . and .. plus and I need to ignore directories. Actually, I might have gotten away without checking for those items and using just the -f check. However, I put those additional checks in there, because I have gotten in trouble in the past for not checking them. So I now have a habit of including those checks whenever I use readdir to look at a directory's contents.
(I did notice that fishmonger showed a different method for finding files in a directory by using grep, but I thought I'd stick with using readdir since that's what you originally were trying to use.)
Also, notice that in the foreach loop that the @files array has only relative file names and not full path file names (i.e. has file.txt and not C:\directory\file.txt). Although I chose to "fix" this in the foreach loop, I could have done the "fix" back in the while loop before adding each file name to the @files array.
Let me share something else. I used to use the readdir method to go find items in a directory. But it can get real cumbersome - especially if you wish to search through subdirectories too. I kept seeing a lot of folks recommending File::Find as a better way to handle that kind of task. As I mentioned in my last post, I never could get my head wrapped around how to use File::Find. At some point I discovered File::Find::Rule and I found it to be super easy to understand how to use. Now when I need to go find and process directory contents, I just use File::Find::Rule. Doing so, I can accomplish the search with 10 or less lines instead of using one or more loops that feel complicated and hoping that I have code that handles everything properly. Although you may be more comfortable with using readdir for this current work, I'd recommend that you look into learning File::Find and/or File::Find::Rule at some point.
|