use strict; use warnings; use File::Copy 'move'; # Determine destination folder for file based on filename. # All destinations are below a fallback destination provided as input. sub make_dest_finder { my $fallback_dest = shift; return sub { my $fnam = shift; # Determine basename to start looking for a destination folder. my $basename = substr $fnam, 0, rindex $fnam, '.'; # Shorten name while no homonymous folder exists. chop $basename while $basename && ! -d "$fallback_dest/$basename"; return "$fallback_dest/$basename" if $basename; return $fallback_dest; }; } my $srcdir = "/tmp/folder"; my $dest_finder = make_dest_finder '/tmp/folder2'; opendir my $dh, $srcdir or die "Can't open $srcdir: $!"; my @files = grep ! /^\.+$/, readdir $dh; close $dh; my $moved = 0; foreach my $file (@files) { my $old = "$srcdir/$file"; my $dest = $dest_finder->( $file ); print STDERR "moving $file to $dest\n"; if ( ! move $old, $dest ) { warn "Move $old -> $dest failed: $!"; last; } $moved++; } print STDERR "\n\n- moved $moved files\n";