Home > Software design >  Rename multiple Files iteratively in bash creates single file
Rename multiple Files iteratively in bash creates single file

Time:11-14

I have the following files in my script's directory:

backup-001.bak backup-002.bak...backup-007.bak

I am trying to rename them in pure bash so that I get:

backup-002.bak backup-003.bak...backup-008.bak

I put together the following simple script which should iteratively rename said files; however, after I run it I end up with only one file backup-008.bak. What am I doing wrong here?

i=2
for file in backup-00[0-7].bak; do
    newname="backup-00$((i)).bak"
    mv -- "$file" "$newname"
  ((  i))
done

CodePudding user response:

for i in {7..1}; do
    mv "backup-00$i.bak" "backup-00$((i 1)).bak" ||
    break
done

Only works for 0-9 (or 100-200 etc) - bash arithmetic won't return zero padded numbers.

CodePudding user response:

You're renaming backup-000.bak to backup-001.bak. Then you rename backup-001.bak to backup-002.bak. This renames the file you created on the previous iteration. And so on through all the files, so you end up renaming backup-000.bak to backup-008.bak.

You should process the files in reverse order:

for ((i = 7; i >= 1; i--)); do
    oldname="backup-00$i.bak"
    newname="backup-00$((i 1)).bak"
    if [ -f "$oldname" ]
    then
        mv -- "$oldname" "$newname"
    fi
done

BTW, Linux has a program logrotate that can automate this.

CodePudding user response:

Considering a minimum index of 1 and a maximum index index of 7; here is a POSIX-shell friendly implementation with correct handling of backup roll and ignoring non-existent backup files.

#!/usr/bin/env sh

i=7
newname=$(printf 'backup-d.bak' $i)
while [ $i -gt 1 ]; do
  i=$((i - 1))
  oldname=$(printf 'backup-d.bak' $i)
  echo mv -f -- "$oldname" "$newname" 2>/dev/null || :
  newname=$oldname
done
  • Related