Created
May 15, 2019 04:36
-
-
Save markasoftware/cfc76f02c880ed43f622cb7be3f0b3c0 to your computer and use it in GitHub Desktop.
SeqSwap
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env perl | |
# Copyright (c) Mark Polyakov 2018 | |
# Released under the GNU GPL version 3 | |
use strict; | |
use warnings; | |
use v5.14; | |
use Cwd 'abs_path'; | |
my $help_text = "USAGE: seqswap out_dir out_prefix out_suffix in_1 [in_2 ...] | |
EXAMPLE: seqswap in out scan_ .png 2,4..:s:scans/left 1,3..:s:scans/right | |
This would take all files from in which have numbers in them, put the evenly | |
numbered ones into scans/left and odd into scans/right, re-numbering them | |
starting from scan_00001.png. Useful for reorganizing scanned books. \n"; | |
my $out_digits = 5; | |
@ARGV >= 4 or die $help_text; | |
my ($rel_out_dir, $out_prefix, $out_suffix, @user_strs) = @ARGV; | |
# remove trailing slash if it exists | |
-d $rel_out_dir or die "Output directory \"$rel_out_dir\" does not exist.\n"; | |
# automatically strips trailing slash | |
my $out_dir = abs_path $rel_out_dir; | |
=pod | |
Format for an input hash: | |
files => @all files individuall, not the folder! | |
start => the number to start at | |
interval => the number to increment by | |
overwrite => 1 if to overwrite, 0 if to skip to the next sequence item instead. | |
=cut | |
# returns a reference to the hash | |
sub user_str_2_input_hash { | |
my $user_str = shift; | |
$user_str =~ /(?<num_1>\d+)(,(?<num_2>\d+))?(?<repeat>\.\.)?:(?<overwrite>[os]):(?<path>.*)/ or die "Invalid user string: $user_str\n"; | |
($+{num_2} and not $+{repeat}) and die "You may not specify an interval without repeat: $user_str\n"; | |
my %input_hash = ( | |
files => [], | |
); | |
$input_hash{start} = $+{num_1}; | |
$input_hash{interval} = $+{num_2} ? $+{num_2} - $+{num_1} : $+{repeat} ? 1 : 0; | |
$input_hash{overwrite} = $+{overwrite} eq 'o'; | |
-e $+{path} or die "Input path $+{path} does not exist.\n"; | |
my $path = abs_path $+{path}; | |
if (-d $path) { | |
opendir my $dir, $path or die "Failed to open directory $path"; | |
# only files that have numbers in them, and sort. We assume same zero padding in each filename so vanilla sort is gucci | |
push @{$input_hash{files}}, map { "$path/$_" } sort grep { $_ =~ /\d+/ } readdir $dir; | |
closedir $dir or die "Failed to close directory $dir"; | |
} else { | |
$path =~ /\d+/ or die "File $+{path} has no number in it.\n"; | |
$input_hash{files}->[0] = $path; | |
} | |
return \%input_hash; | |
} | |
my @input_hashes = map { user_str_2_input_hash $_ } @user_strs; | |
# keys are the output number, values are the input filenames | |
my %out_nums = (); | |
for my $input_hash (@input_hashes) { | |
my $out_num = $input_hash->{start}; | |
for my $file (@{$input_hash->{files}}) { | |
my $should_skip = ($out_nums{$out_num} and not $input_hash->{overwrite}); | |
$out_nums{$out_num} = $file unless $should_skip; | |
# if only one number was specified on the command line, we're done. | |
last if $input_hash->{interval} == 0; | |
$out_num += $input_hash->{interval}; | |
# keep the same file if we skipped | |
redo if $should_skip; # perl is so fucking nice | |
} | |
} | |
# ezpz | |
my $t = 0; | |
for my $out_num (keys %out_nums) { | |
# PERL IS SO FUCKIN SICK! | |
my $padded_out_num = '0' x ($out_digits - length $out_num) . $out_num; | |
my $out_filename = $out_dir . '/' . $out_prefix . $padded_out_num . $out_suffix; | |
symlink $out_nums{$out_num}, $out_filename or die "Failed to create symlink from $out_nums{$out_num} to $out_filename\n"; | |
$t++; | |
} | |
say "Processed $t files without error."; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment