92

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 
Benjamin W.
  • 46,058
  • 19
  • 106
  • 116
user3115029
  • 929
  • 1
  • 7
  • 3
  • 1
    Several possibilities, described here - http://stackoverflow.com/questions/6114004/add-file-extension-to-files-with-bash – Tom Ron Dec 18 '13 at 12:02
  • This answer may also be useful: [https://unix.stackexchange.com/questions/316038/change-part-of-the-filename-on-multiple-files-in-a-directory](https://unix.stackexchange.com/questions/316038/change-part-of-the-filename-on-multiple-files-in-a-directory) – bfischi Dec 23 '21 at 18:06

6 Answers6

192

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.

Tim Zimmermann
  • 6,132
  • 3
  • 30
  • 36
  • 53
    Where has this command been all my life?! – sanmiguel Dec 18 '13 at 12:36
  • 7
    This implementation of rename is version dependent, the other answer shows the same command with a different implementation syntax. – Will Barnwell Aug 15 '17 at 18:49
  • 3
    This does not work with the rename included in Fedora 25. I had to do `rename test-this REPLACESTRING *`. Anyone know which package to install in fedora to get the type of rename mentioned in the answer? – Aditya Kashi Oct 18 '17 at 17:08
  • @Aditya This is Perl rename, `prename`. On Fedora, I believe the package is just called `prename`. – wjandrea Aug 12 '18 at 21:13
  • can I have the answer for macOS? it says `zsh: command not found: rename` – Dylan Jul 29 '20 at 00:19
  • This worked great. I just installed the `rename` package, and puff, I was able to rename all my files. – muammar Oct 01 '20 at 18:22
  • Note the `-n` flag which lets you dry run it ahead of time (there is no undo :). – studgeek Nov 18 '20 at 01:51
  • 2
    @Dylan `brew install rename` – alandawkins May 07 '21 at 06:21
  • On Ubuntu I did have to do this: `rename.ul '.html' '.html.erb' ./*.html` - note "rename.ul", and passing 3 arguments (regex, replacement and list of files) instead of just a substring in this answer. – Serge Vinogradov Jun 04 '21 at 01:29
  • That's why all the other comments here already explain that the one you are using is the utility in the other `rename` answer. – tripleee Jun 06 '21 at 10:27
  • I needed to do `sudo apt-get install rename` on a Ubuntu 18 machine. I was using `mv` earlier and that didn't help with multiple files. `rename` did – S Raghav Feb 24 '22 at 11:20
80

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
dogbane
  • 266,786
  • 75
  • 396
  • 414
  • 3
    Note this is the [util-linux `rename`](http://man7.org/linux/man-pages/man1/rename.1.html), not the Perl `rename` mentioned in another answer. – wjandrea Aug 12 '18 at 21:21
  • 2
    This seems to the be rename command that is included with my Centos distro. Apparently the other rename is not universal to Linux. – Leslie Krause Feb 14 '19 at 04:22
  • 1
    Neither of them is universal. That's why we need two separate answers. Probably the answer itself should be more explicit and detailed about this. – tripleee Jun 06 '21 at 10:28
30

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 
Deepak Mahakale
  • 22,834
  • 10
  • 68
  • 88
Joe Flack
  • 866
  • 8
  • 14
  • 27
    If you have Homebrew, you can install `rename` with `brew install rename` – harryscholes Jun 01 '18 at 08:39
  • the `for i in $1*` syntax should generally be avoided as it will break on paths with spaces, stars, quotes and other funny characters; `find . -iname "$1" -exec sh -c 'do work here' {} \;` is more reliable since it will handle correctly any paths. – ccpizza Jan 18 '23 at 13:04
12

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.

user16785526
  • 131
  • 1
  • 6
  • 1
    This answer is the UNIX way. This answer applies to an unfathomable number of applications and will support skipping over the clouds like a UNIX GOD. The rename answer is a one-off. – Dell Kronewitter Sep 11 '22 at 16:42
1

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.

Shanavas M
  • 1,581
  • 1
  • 17
  • 24
J Wiese
  • 11
  • 1
-2

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

Rogoit
  • 81
  • 7