Quite a few similar question are being asked. The error is probably staring at me in the face, but I just can't see it...

declare -a files
shopt -s nullglob       
count=36   # offset

for oldfilename in "${files[@]}"; do
    (( count++ ))
#   newfilename=$(echo "$oldfilename" | sed -e "s/^[1-9][0-9]?\.jpg/Scount\.png/")
#   newfilename=${oldfilename/[1-9][0-9]?/Scount}
#   newfilename=${oldfilename/[1-9][0-9]?/"Scount"}
    echo mv -fv /path1/to/"${oldfilename}" /path2/to/"${newfilename}"
exit 0

I have tried commented lines. I don't know the difference between / and // in newfilename=${oldfilename/[1-9][0-9]?/"Scount"}. o_0 ?

EDIT: Files represented by $oldfilename have the form 1.jpg to 99.jpg. Output files $newfilename are expected to have the form 37.png to 135.png (at least as far as the sed invocation goes).
Somehow files are not renamed and the dot in .jpg disappears. Why does this not work ?

  • 2
    Sample of input filenames and to what you expect them to be transformed please Jan 7, 2016 at 22:13
  • 1
    Shouldn't that be $count instead of Scount? And, if so, you probably rather want $(printf "%02d" $count) to keep file names length constant (i.e. keep leading zeroes).
    – peterph
    Jan 7, 2016 at 22:16
  • Is that an S in stead of a $ where you attempt to define newfilename?
    – joepd
    Jan 7, 2016 at 22:18
  • 1
    Can you clarify what is happening? ("not working" is pretty vague.)  Also, please clarify what you want to happen.  It looks like you want to rename 1.jpg37.jpg, 2.jpg38.jpg, etc.  But what if you already have a file named 37.jpg or 38.jpg?  Does the sed version work when you replace Scount with $count?  (And do you really want to rename *.jpg files to *.png?) Jan 8, 2016 at 1:17
  • Sorry to all for lacking in details. Somehow they're evident to me but understandably not to others. Here goes... @roaima : input file name have the form 1.jpg to 99.jpg. Output file names have the form 37.png to 135.png. @perterph: Thanks. It definitely should be $count instead of my nonsensical Scount. Leading zeroes for filenames starting with one or two digit numerals are already taken care of in the routine in which this snippet is inserted.
    – Cbhihe
    Jan 8, 2016 at 7:48

2 Answers 2


I guess from your (commented out) sed command that you want to match and replace a regular expression: [1-9][0-9]?, meaning

  • a non-zero digit ([1-9]), followed by
  • zero or one digit(s) ([0-9]?)

which is a fairly common regex for an integer between 1 and 99 (with no leading zero).  However, ${parameter/pattern/string} doesn't use regexs, it uses pathname expansion patterns (a.k.a. wildcards).  So [1-9][0-9]? means

  • a non-zero digit ([1-9]), followed by
  • a digit ([0-9]), followed by
  • any character (?)

Still, it should have worked for the two-digit filenames, although it would consume the . and rename 10.jpg to 46jpg (without .).

Regarding the other part of your question, // replaces all occurrences of the pattern, while / replaces only the first.  For example,

$ i=cataract
$ echo "${i/a/X}"
$ echo "${i//a/X}"

If you have the Perl rename (sometimes called prename) you can do this:

rename -v 's!(\d+)(.*)\.jpg$!sprintf "%d%s.png", $1+36, $2!e' *.jpg

This takes each filename, splits off the leading digits, the rest of the filename component, and the trailing .jpg. It then adds 36 to the numeric part, adds on the remainder of the original filename, and replaces the suffix with .png.

Use rename -n ... to see what would happen with it changing anything, or remove the -v to have it run silently.


You must log in to answer this question.

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