Hi I am looking for a bash solution to batch file renaming. I have files acquired from a digital camera I am importing as time-lapse footage.

Every 1000 images the JPG file renaming jumps as such:


I am trying to hack a reusable shell command that lets me remove the '0' in the 5th position such that the image count is contiguous for importing to After Effects.

Does anybody know the quickest and easiest way to remove the nth character in a set of filenames? I will always have the image set together in a directory with no other files than the image sequence in said directory.

I have searched and solutions so far would seem to remove all '0' characters from the filename which is not what I want; specifically only removing the 5th character is my desired result. Thank you for any time taken to answer this.

  • Consider using the right tool to save yourself time and trouble. This job can be done in just a couple of seconds using the "bulkrename" option of the "ranger" application (github.com/ranger/ranger).
    – user492570
    Commented Dec 14, 2021 at 14:11

4 Answers 4


It's worth citing the relevant man page of the feature you're using. From the EXPANSION section of man bash:

       Substring  Expansion.  Expands to up to length characters of the value of parameter starting at the character specified by offset.  If parameter is @, an 
       indexed array subscripted by @ or *, or an associative array name, the results differ as described below.  If length is omitted, expands to the substring
       of  the value of parameter starting at the character specified by offset and extending to the end of the value.  length and offset are arithmetic expres‐
       sions (see ARITHMETIC EVALUATION below).

       If offset evaluates to a number less than zero, the value is used as an offset in characters from the end of the value of parameter.  If length evaluates
       to  a  number less than zero, it is interpreted as an offset in characters from the end of the value of parameter rather than a number of characters, and
       the expansion is the characters between offset and that result.  Note that a negative offset must be separated from the colon by at least  one  space  to 
       avoid being confused with the :- expansion.

Note that you can perform arithmetic inside ${}, so you could parameterize your code like this:


for f in *JPG; do
   mv -- "$f" "${f:0:$position-1}${f:$position}"


This is a quick-and-dirty solution which doesn't check for the length of filenames or anything, but for a hack like this it should be ok.


Use rename (Perl rename or prename).

rename -nv 's/^(.{4})0/$1/' ./*.jpg

we substitute:

  • ^ asserts position at start of the string
  • (.{4}) is 1st Capturing Group with back-reference to the $1; the dot . matches any character (except \newline) and with {4} it matches the previous token exactly 4 times.
  • 0 matches the character 0.

with content of Capturing Group $1 above only, which it results to remove 0 character at the 5th character position (you can replace 0 with . to remove any character (except \newline) at the 5th position instead of always matching on 0 character).

generated on regexper.com

  • Could you translate this line?
    – A H
    Commented Jul 29, 2020 at 0:08
  • @AH sorry for the late response, I added some explanation Commented Dec 14, 2021 at 12:51

Nevermind! Figured out the shell script solution. For those who are here because they have the same problem here is the shell code I used:

cd DIRECTORYPATH         ## Navigate to directory with images

for f in *; do           ## Begin for loop with each file in directory
    x="${f::4}"          ## Set x as first 4 characters
    y="${f:5}"           ## Set y as all characters past position 5
    mv -- "$f" "$x$y"    ## Use mv command to rename each file as string x+y

Another way is to use sed



for f in *.JPG 
    mv $f $(echo $f | sed -e 's/\(^P[0-9]\{3\}\)0\([0-9]*\.JPG\)/\1\2/')


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .