Rename files according to date

I recently wrote a Perl script, that renames the files in a directory according to the date, in the format “YYYYMMDD ##” where “##” is the running number.

Rationale

Because I used to download the photos using the mobile apps like Weibo or Twitter, however the file names are almost random. This made me hard to organize these photos on my computer.

The artists (or celebrities) usually share a set of their photos, so when I download these photos, the files should have mtime (modified time) in the correct order.

Yet, I don’t need to rename the file to the time precision like “HH:MM:SS”. I just need the date and followed by the running number, because it looks shorter.

Though we can just use the file browsers to sort the files according to the time, it is still inconvenient to browse the images by changing the sorting condition. Furthermore, mtime can be changed, and this will void the purpose of the sorting.

Lastly, the randomized filename is just meaningless to me. Rename them according to the date is much more useful, in my opinion.

 

Script


#!/usr/bin/perl -w
use strict;
use warnings;
use POSIX 'strftime';
use File::Basename;
sub trim { my $s = shift; $s =~ s/^\s+|\s+$//g; return $s };
sub get_files_from_directory {
my $path = $_[0];
opendir my $dir, $path or die "Cannot open directory: $!";
my @files = readdir($dir);
@files = grep(!/^\.$|^\.\.$/, @files);
closedir $dir;
return @files;
}
sub group_files_by_date {
my ($dir, @files) = @_;
my %groups = ();
foreach my $file (@files) {
my $timestamp = (stat "$dir/$file")[9];
my $date = strftime("%Y%m%d", localtime($timestamp));
if (not exists $groups{$date}) {
@{$groups{$date}} = ();
}
push @{$groups{$date}}, "$dir/$file";
}
return %groups;
}
sub sort_files_in_groups {
my (%groups) = @_;
foreach my $key (sort keys %groups) {
my $files = $groups{$key};
@{$groups{$key}} = sort { (stat $a)[9] <=> (stat $b)[9] } @{$files};
}
return %groups;
}
sub build_new_name {
my ($date, $num, $dir, $ext) = @_;
my $zero_num = sprintf("%02d", $num);
return "$dir${date} ${zero_num}${ext}";
}
sub name_pairs {
my (%groups) = @_;
my %pairs;
foreach my $key (keys %groups) {
my $files = $groups{$key};
for (my $i = 0; $i < scalar @{$files}; $i++) {
my $file = @{$files}[$i];
my ($basename, $dir, $ext) = fileparse($file, qr/\.[^.]*/);
my $new_name = &build_new_name($key, $i + 1, $dir, $ext);
$pairs{$file} = $new_name;
}
}
return %pairs;
}
sub print_pairs {
my (%pairs) = @_;
foreach my $key (keys %pairs) {
print "$key\t->\t$pairs{$key}\n";
}
}
sub rename_files {
my (%pairs) = @_;
foreach my $key (keys %pairs) {
rename $key, $pairs{$key};
}
}
sub save_log {
my (%pairs) = @_;
my $file = 'rename_files_to_date.log';
open(my $fh, '>', $file);
foreach my $key (keys %pairs) {
print $fh "$key\t->\t$pairs{$key}\n";
}
close $fh;
}
sub main {
my @argv = @_;
my $dir = $argv[0];
my @files = &get_files_from_directory($dir);
my %groups = &group_files_by_date($dir, @files);
%groups = &sort_files_in_groups(%groups);
my %pairs = &name_pairs(%groups);
&print_pairs(%pairs);
print "\nWARNING: Rename is irreversible. Recommend to make a backup.\n",
"Confirm rename files? (y/N) ";
my $choice = <STDIN>;
print $choice;
exit 0 unless trim($choice) eq 'y';
&rename_files(%pairs);
&save_log(%pairs);
print "Done. Log file also saved.\n";
}
&main(@ARGV);

 

Why Perl?

In my opinion, Perl is less famous like Python in the present day. But I prefer to use Perl, due to the popularity in most Linux distribution. For example Perl is the base package of Arch Linux. Once I installed Arch Linux, I can run Perl script immediately.

Though Python is great, backward incompatibility sometimes causes issue, which I may need to maintain the script. If I write with Perl, I can pay less effort to maintain the script.

 

WARNING! And usage

As the script mentioned,

Rename is irreversible. Recommend to make a backup.

The usage is,

./rename_files_to_date.pl ./target_dir

Where target_dir is the directory that contains the files you want to rename. It will not rename the files recursively.

PLEASE USE THE SCRIPT AT YOUR OWN RISK!!!

After renaming the files, a log file will be created. It is used just in case you want to revert the file name. (But you have to do this manually.)