#!/usr/bin/perl use strict; use warnings; use File::Find; use Data::Dumper; use Win32::Hardlink; use Image::ExifTool qw/ImageInfo/; my $source = "C:\\Photos"; my $dest = "C:\\Photos_Organized"; my $main = { Dates => {}, Tags => {}, }; find(\&wanted, $source); sub wanted { my $file = $File::Find::name ; if (-f $file) { my $date_tag = ''; my $info = ImageInfo($file,['XmpmetaSubject','CreateDate']); my @keywords = map { $info->{$_} } grep { /^XmpmetaSubject/ } keys %$info; if (defined $info->{CreateDate} && $info->{CreateDate} =~ /^(\d\d\d\d):(\d\d):(\d\d)/) { $date_tag = "$1/$2/$3"; } add_picture($main, $file, $_, $date_tag, @keywords); print "$file [", join(",", @keywords), "] [$date_tag] \n"; } } sub build_dir { my $dir = shift; unless (-d $dir) { mkdir $dir or die "Failed to create $dir: $!"; } } sub link_tag { my ($base_dir, $src, $file_name, $tags) = @_; my $base_tag = ''; my @tags = split /\//, $tags; for (@tags) { $base_tag .= "$_\\"; build_dir($base_dir . $base_tag); my $dest = $base_dir . $base_tag . $file_name; unlink($dest) if -f $dest; link($src=> $dest); } } sub add_picture { my ($main, $file, $name, $date, @tags) = @_; my ($y,$m,$d) = split /\//, $date; link_tag("$dest\\By Date\\", $file, $name, $date); link_tag("$dest\\By Tag\\", $file, $name, $_) for @tags; link_tag("$dest\\By Tag\\", $file, $name, 'All'); }