1

I want to rename the files in a directory to sequential numbers.

stars_01_012.png
stars_01_014.png
stars_01_015.png
stars_01_017.png
stars_02_012.png
stars_02_014.png
stars_02_015.png
stars_02_017.png

And change it into

stars_01_001.png
stars_01_002.png
stars_01_003.png
stars_01_004.png
stars_02_001.png
stars_02_002.png
stars_02_003.png
stars_02_004.png

Relatives but not completely: How to Batch Rename Files in a macOS Terminal? How can I batch rename files using the Terminal?

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
CJ Yen
  • 43
  • 1
  • 6
  • Are your files named exactly like that? Or are there some that start with, say, `planets_01`? Or any with 3 underscores? Or 3 sets of numbers? Or some JPEGs? – Mark Setchell Jul 03 '20 at 16:10

3 Answers3

1

You can also create an applescript script, using the Terminal commandline. below a script to copy in the script editor set thefile to do shell script "ls The_path_of_your_files" that you wish to rename '"with in common the extension (in your example .png) which gives:

**set thefile to do shell script "ls The_path_of_your_files/*.png"

set AppleScript's text item delimiters to return
set chFile to text items of thefile
set AppleScript's text item delimiters to ""
set n to count chFile
repeat with i from 1 to n
set rnFile to item i of chFile
set nwname to (do shell script "echo" & quoted form of rnFile & "| sed 's # stars_01_01 # stars_01_00 #'")
         set endFile to (do shell script "mv -f" & quoted form of rnFile & "" & quoted form of nwname)
end repeat**

which is equivalent to the rename multiple files function of the Finder

deek5
  • 367
  • 1
  • 13
1

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.

Mark Setchell
  • 191,897
  • 31
  • 273
  • 432
0

Just a rough answer, why use terminal script? You can just use the Finder with its rename function by selecting the common part of all your files in your example "stars_01_01" and replacing it with "stars_01_00", this will lead to the same result without having to write a script with :

sed 's#stars_01_01#stars_01_00#g'

deek5
  • 367
  • 1
  • 13
  • Thank you, but I need the digital stay in 3 digits, when it meets up to 10, it will generated the 4 digits number: stars_01_009 stars_01_0010 – CJ Yen Jul 09 '20 at 07:41