You can do it with rename
which you can install on macOS with homebrew using:
brew install rename
The command then looks like this:
rename --dry-run -X -e 'my @parts=split /_/; my $this=$parts[0].$parts[1]; if(!defined($ENV{previous}) || $this ne $ENV{previous}){$ENV{previous}=$this; $ENV{N}=0}; $ENV{N}=$ENV{N}+1; $_ = $parts[0]."_".$parts[1]."_".$ENV{N}' *png
Sample Output
'stars_01_012.png' would be renamed to 'stars_01_1.png'
'stars_01_014.png' would be renamed to 'stars_01_2.png'
'stars_01_015.png' would be renamed to 'stars_01_3.png'
'stars_01_017.png' would be renamed to 'stars_01_4.png'
'stars_02_012.png' would be renamed to 'stars_02_1.png'
'stars_02_014.png' would be renamed to 'stars_02_2.png'
'stars_02_015.png' would be renamed to 'stars_02_3.png'
'stars_02_017.png' would be renamed to 'stars_02_4.png'
'stars_88_099.png' would be renamed to 'stars_88_1.png'
Explanation:
my @parts=split /_/
splits the filename into 3 parts using the underscore as the separator,
my $this=$parts[0].$parts[1]
saves the first two parts simply concatenated together, e.g. "stars01",
the if
statement tests if either of the first two parts have changed, then
$ENV{previous}=$this; $ENV{N}=0
saves the current stem of the filename in an environment variable called previous
and the current sequential counter in another environment variable N
,
$ENV{N}=$ENV{N}+1
increments the sequential counter, and
$_ = $parts[0]."_".$parts[1]."_".$ENV{N}
creates the new output filename from the various parts.
If that all looks correct, remove the --dry-run
and run it again - probably in a spare directory with a copy of your files until you are sure all is ok :-)
The above may be easier to read like this:
#!/bin/bash
rename --dry-run -X -e '
my @parts=split /_/; # split filename into parts based on underscore
my $this=$parts[0].$parts[1]; # save first two parts of filename in $this
# see if it is a new stem
if(!defined($ENV{previous}) || $this ne $ENV{previous}){
$ENV{previous}=$this; $ENV{N}=0}; # save new initial part, reset N
$ENV{N}=$ENV{N}+1; # increment N
$_ = $parts[0]."_".$parts[1]."_".$ENV{N} # formulate new filename from parts
' *png
Change the last line to the following if you want to zero-pad the numbers out to three digits:
$_ = sprintf("%s_%s_%03d",$parts[0],$parts[1],$ENV{N}) # formulate new filename from parts
Note:
I save the previous file prefix and sequential counter into environment variables to preserve them between files - there may be easier ways - if anyone knows, please ping me! Thanks.