Files
symlink-images-by-aspect-ratio/symlink-images-by-aspect-ratio.pl
2026-02-27 15:38:30 +01:00

135 lines
3.6 KiB
Perl
Executable File

#!/usr/bin/perl
use warnings;
use strict;
use File::Find::Wanted;
use File::Basename;
use File::Spec;
use File::Spec::Functions;
use Image::Size;
use Data::Dumper::Simple;
use Math::Round;
my $conf = {
src_dir => "./slike",
dst_dir => "./linki",
debug => 0,
};
sub msg {
my $text = shift;
print $text;
}
sub msg_error {
my $text = shift;
print STDERR "ERROR: $text";
}
sub msg_warn {
my $text = shift;
print STDERR "warning: $text";
}
sub msg_debug {
my $text = shift;
print "$text" if $conf->{debug};
}
# verify the source dir
if (! -d $conf->{src_dir}) {
msg_error "Source directory '$conf->{src_dir}' does not exist. Aborting.\n" ;
exit 1;
}
# verify the destination dir
if (! -d $conf->{dst_dir}) {
msg_error "Destination directory '$conf->{dst_dir}' does not exist. Aborting.\n";
exit 1;
}
# gather the list of files
my @list = find_wanted(
sub { -f && ( /\.jpg$/i || /\.jpeg$/i ) },
$conf->{src_dir}
);
if (! @list) {
msg "No files found.\n";
exit 0
}
# Go through all the image files and build the hash that holds all the
# information about them.
my $count = 0; # how many files?
my $errors = 0; # how many errors?
my $ars = {}; # a hashref that holds all the encountered aspect rations and their number of occurence
my $files = {}; # a hashref that holds all the files, their exif data, and their calculcated aspect ratio
foreach my $f (@list) {
$count++;
msg "Gathering sizes for image in file: '$f'\n";
(my $x, my $y) = imgsize($f);
# calculate aspect ratio
my $ar;
if ($x and $y) {
$ar = nearest(0.1, ($x > $y) ? $x / $y : $y / $x);
$ars->{$ar}++;
}
else {
$errors++;
}
# append the stuff to hash
$files->{$f}->{x} = $x;
$files->{$f}->{y} = $y;
$files->{$f}->{ar} = $ar;
}
# Dump the hash data if we are in debug mode.
if ($conf->{debug}) {
msg_debug "All images and their data:\n";
print Dumper $files;
msg_debug "\n";
}
# Dump some statistics.
msg "Number of images found: $count. Number of images with errors: $errors.\n";
msg "Aspect ratio information for all images (aspect ratio => number of occurences):\n";
print Dumper $ars;
# Create destination directories. TODO: use something smarter than just string
# concatenation.
msg_debug "Creating destination directories: ";
foreach my $d (keys %$ars) {
my $dirname = $conf->{dst_dir} . "/" . $d;
msg_debug "'$dirname' ";
mkdir $dirname;
}
msg_debug "\n";
# Symlink
msg "Symlinking source files into destination directories.\n";
foreach my $f (keys %$files) {
next unless exists $files->{$f}->{ar};
# Construct the path of the symlink. This is quite tricky to get right.
# TODO: use something smarter than just string concatenation.
msg_debug "\$f='$f' ";
my $ar = $files->{$f}->{ar}; msg_debug "\$ar='$ar' ";
my $symlink_dir = $conf->{dst_dir} . "/" . $ar; msg_debug "\$symlink_dir='$symlink_dir' ";
my $symlink = $symlink_dir . "/" . basename($f); msg_debug "\$symlink='$symlink' ";
my $symlink_dst = File::Spec->abs2rel(
File::Spec->rel2abs($f),
File::Spec->rel2abs($symlink_dir)
);
msg_debug "\$symlink_dst='$symlink_dst' ";
msg_debug "\n";
# Create the symlink.
msg_debug "symlink($symlink_dst, $symlink);\n";
symlink($symlink_dst, $symlink);
}
# vim: set ts=4 sw=4 et cc=80: