'Rename multiple files, but only rename part of the filename in Bash

I know how I can rename files and such, but I'm having trouble with this.

I only need to rename test-this in a for loop.

test-this.ext
test-this.volume001+02.ext
test-this.volume002+04.ext 
test-this.volume003+08.ext 
test-this.volume004+16.ext 
test-this.volume005+32.ext 
test-this.volume006+64.ext 
test-this.volume007+78.ext 


Solution 1:[1]

If you have all of these files in one folder and you're on Linux you can use:

rename 's/test-this/REPLACESTRING/g' *

The result will be:

REPLACESTRING.ext
REPLACESTRING.volume001+02.ext
REPLACESTRING.volume002+04.ext
...

rename can take a command as the first argument. The command here consists of four parts:

  1. s: flag to substitute a string with another string,
  2. test-this: the string you want to replace,
  3. REPLACESTRING: the string you want to replace the search string with, and
  4. g: a flag indicating that all matches of the search string shall be replaced, i.e. if the filename is test-this-abc-test-this.ext the result will be REPLACESTRING-abc-REPLACESTRING.ext.

Refer to man sed for a detailed description of the flags.

Solution 2:[2]

Use rename as shown below:

rename test-this foo test-this*

This will replace test-this with foo in the file names.

If you don't have rename use a for loop as shown below:

for i in test-this*
do
    mv "$i" "${i/test-this/foo}"
done

Solution 3:[3]

Function

I'm on OSX and my bash doesn't come with rename as a built-in function. I create a function in my .bash_profile that takes the first argument, which is a pattern in the file that should only match once, and doesn't care what comes after it, and replaces with the text of argument 2.

rename() {
    for i in $1*
    do
        mv "$i" "${i/$1/$2}"
    done
}

Input Files

test-this.ext
test-this.volume001+02.ext
test-this.volume002+04.ext 
test-this.volume003+08.ext 
test-this.volume004+16.ext 
test-this.volume005+32.ext 
test-this.volume006+64.ext 
test-this.volume007+78.ext 

Command

rename test-this hello-there

Output

hello-there.ext
hello-there.volume001+02.ext
hello-there.volume002+04.ext 
hello-there.volume003+08.ext 
hello-there.volume004+16.ext 
hello-there.volume005+32.ext 
hello-there.volume006+64.ext 
hello-there.volume007+78.ext 

Solution 4:[4]

Without using rename:

find -name test-this\*.ext | sed 'p;s/test-this/replace-that/' | xargs -d '\n' -n 2 mv

The way it works is as follows:

  1. find will, well, find all files matching your criteria. If you pass -name a glob expression, don't forget to escape the *.

  2. Pipe the newline-separated* list of filenames into sed, which will:

    a. Print (p) one line.

    b. Substitute (s//) test-this with replace-that and print the result.

    c. Move on to the next line.

  3. Pipe the newline-separated list of alternating old and new filenames to xargs, which will:

    a. Treat newlines as delimiters (-d '\n').

    b. Call mv repeatedly with up to 2 (-n 2) arguments each time.

For a dry run, try the following:

find -name test-this\*.ext | sed 'p;s/test-this/replace-that/' | xargs -d '\n' -n 2 echo mv

*: Keep in mind it won't work if your filenames include newlines.

Solution 5:[5]

to rename index.htm to index.html

rename [what you want to rename] [what you want it to be] [match on these files]
rename .htm .HTML *.htm

renames index.htm to index.html It will do this for all files that match *.htm in the folder.

Solution 6:[6]

thx for your passion and answers. I also find a solution for me to rename multiple files on my linux terminal and directly add a little counter. With this I have a very good chance to have better SEO names.

Here is the command

count=1 ; zmv '(*).jpg' 'new-seo-name--$((count++)).jpg'

I also do a live coding video and publush it to YouTube

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 dogbane
Solution 3 Deepak Mahakale
Solution 4 user16785526
Solution 5 Shanavas M
Solution 6 Rogoit