Home > Net >  rename file by adding a value using bash
rename file by adding a value using bash

Time:04-11

I have a series of files with similar extension in a directory and it's subdirectories. I'd like to add a constant value to their integer part of the basename. Is there any way to do it using Bash? Let's take following example.

Before: ../ParentDirectory/Directory/123-File.ext

after adding 20 to the integer part (123 20=143): ../ParentDirectory/Directory/143-File.ext

I assume a series of FIND and RENAME commands are needed, but I'm not sure how!

CodePudding user response:

Assuming:

  • The top directory is "ParentDirectory" and its subdirectories contain the files to be renamed.
  • The files have extension ".ext".
  • The filenames start with the number and do not contain other numbers in the middle of the filenames.

Then would you please try the bash script:

#!/bin/bash

find ParentDirectory -type f -name "*.ext" | while IFS= read -r path; do
    dir=${path%/*}              # extract the directory name
    fname=${path##*/}           # extract the file name
    num=${fname//[^0-9]/}       # number part of the file name
    remain=${fname//[0-9]/}     # remaining part of the file name
    (( num  = 20 ))             # add 20 to the number
    newpath="$dir/$num$remain"  # compose the new filename
    if [[ -f $newpath ]]; then  # make sure the new filename doesn't duplicate
        echo "$newpath already exists. skip renaming."
    else
        echo mv -- "$path" "$newpath"
                                # print the mv command
    fi
done

It outputs the mv commands as a dry run. If the output looks good, drop echo before mv command and run again.

As Barmar suggests, if perl rename command is available, please try instead:

shopt -s globstar
rename -n 's/\d (?!.*\/)/$&   20/e' ParentDirectory/**/*.ext
  • The regex \d (?!.*\/) matches number not followed by a slash. It avoids to match numbers included in the directory names.
  • The e modifier at the end of the rename command tells perl to evaluate the substitution $& 20 as a perl expression rather than a literal substitution string.
  • ParentDirectory/**/*.ext is expanded recursively due to the shopt -s globstar option.
  • The -n option just prints the filenames with no action. If the output looks good, drop -n.

Please note there are two different rename commands: "perl rename" and "non-perl rename" depending on the distribution. You can determine which one is installed by taking a look of man rename. If it includes the word Perl, it is the perl rename command.

  • Related