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 therename
command tellsperl
to evaluate the substitution$& 20
as a perl expression rather than a literal substitution string. ParentDirectory/**/*.ext
is expanded recursively due to theshopt -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.