Search code examples
bashfile-rename

Incrementing a number, problem in change from 19 to 20, as it turns it into 110 instead


I have a script that I've been using to increment a file name. The files are called something like "YYYY-MM-DD name V. 23". As long as there's no jump to the next 10 it works great, which is why I hadn't noticed a problem so far. But when it shifts to the next 10, it doesn't seem to see the whole number but just the last digit. It has something to do with Bash-Rematch, but I can't figure it out.

#!/bin/bash

fileName=$1

today=$(date +"%Y-%m-%d")


if [[ $fileName =~ ([0-9]+-[0-9]+-[0-9]+)(.*)([0-9]+)\.([^.]*) ]]; then
  # BASH_REMATCH match groups:
  # 1 - date
  # 2 - everything else
  # 3 - number
  # 4 - extension

  number=$(( ${BASH_REMATCH[3]} + 1 ))

  while :; do
        newFileName="$(date +%Y-%m-%d)${BASH_REMATCH[2]}${number}.${BASH_REMATCH[4]}"
        [[ -f $newFileName ]] || break
        let "number++"
  done

  echo "copy $fileName to $newFileName"
  cp "$fileName" "$newFileName"

elif [[ $fileName =~ (.*)\.([^.]*) ]]; then
    newNumber="1"
    addInfoName="$today ${BASH_REMATCH[1]} V.${newNumber}.${BASH_REMATCH[2]}"

    mv "$fileName" "$addInfoName" 
    let "newNumber++"
    cp "$addInfoName" "$today ${BASH_REMATCH[1]} V.${newNumber}.${BASH_REMATCH[2]}"
fi

The script is supposed to check if the date at the start of the file is that of today (if not change that while copying the file), then see if there's a number at the end (if not add one) and increment that number by 1.

E.g. if I trigger the script on 2023-09-25 Letter Application V.3 it turns into 2023-10-28 Letter Application V.4

How do I get the script to consider the whole number at the end (e.g. 29) so that it turns into the next 10 (e.g. 30 and not 210)?

ChatGPT and similar suggested adding [[:space:]] around the number in the regex field (e.g. ([0-9]+-[0-9]+-[0-9]+)(.*)([[:space:]][0-9]+[[:space:]])(\.[^.]*)$), but that causes the number (and the date at the start) to not be recognized at all, so it then looks like 2023-10-28 2023-09-25 Letter Application V. 29 V. 1


Solution

  • It seems to me that your issue is not about the 2-digit number. The RE doesn't match the string pattern that you have indicated.

    • Your string pattern: YYYY-MM-DD name V. 23
    • Your RE: ([0-9]+-[0-9]+-[0-9]+)(.*)([0-9]+)\.([^.]*)

    According to the RE, the string ends with number.extension, which is not true.

    I think the RE you need is ([0-9]+-[0-9]+-[0-9]+)\s+(.+)\s+V\.\s+([0-9]+).

    Check demo.

    Note that I tested this with PCRE, you may want to replace \s with [[:space:]]:

    ([0-9]+-[0-9]+-[0-9]+)[[:space:]]+(.+)[[:space:]]+V\.[[:space:]]+([0-9]+)