I want to rename multiple files in the same directory using Bash scripting. Names of the files are as follows:


I want to rename to the following format:


I was reading about the rename command, and try to do it this way, but it does nothing, I think I have questions about the syntax. Then I read that you can make a loop using the mv command as follows:

for file in cmpsms*2014*.p; do
    mv "$file" "${file/cmpsms*2014*.p/cmpsms25032014*.p}"

But I can not rename the files. What am I doing wrong?

  • possible duplicate of How can I rename a lot of files using a regex?
    – Kiwy
    Commented Mar 26, 2014 at 14:09
  • 2
    You can't have a pattern expression on the right hand side of a parameter expansion replacement expression. What did you expect to be where that * is?
    – kojiro
    Commented Mar 26, 2014 at 14:22
  • @Kiwy That question is about removing a portion of the file name. Ergo, highly doubtfully duplicate.
    – user
    Commented Mar 26, 2014 at 14:41
  • 2
    Next time, please describe the file name changes you want to make (I had to look at this for a fair while before seeing the differences and similarities). Examples are good, but a description as well as examples is even better.
    – user
    Commented Mar 26, 2014 at 14:43

6 Answers 6


You were right to consider rename first. The syntax is a little strange if you're not used to regexes but it's by far the quickest/shortest route once you know what you're doing:

rename 's/\d{4}/2503/' file*

That simply matches the first 4 numbers and swaps them for the ones you specified.

And a test harness (-vn means be verbose but don't do anything) using your filenames:

$ rename 's/\d{4}/2503/' file* -vn
file0901201437404.p renamed as file2503201437404.p
file0901201438761.p renamed as file2503201438761.p
file1003201410069.p renamed as file2503201410069.p
file2602201409853.p renamed as file2503201409853.p
file2602201410180.p renamed as file2503201410180.p
  • 9
    Note that this is the Perl rename on Debian and derivatives (Ubuntu, Mint, …). On other Linux distributions, rename is a completely different file renaming tool (which Debian ships as rename.ul). Commented Mar 26, 2014 at 20:33
  • If your distributive lack of such tool, look at @Michael Campbell answer. I think every distributive replace default rename like debian did.
    – Astery
    Commented Sep 18, 2015 at 10:08

This should do the trick:

for f in file*; do mv $f ${f/${f:4:8}/25032014}; done

It replaces the string beween the 4th and the 12th character with "25032014".

  • this for f in file*; do mv $f ${f/${f:4:4}/2503}; done also work. Commented Mar 26, 2014 at 16:36
  • That's nice. If you just want to do a regular word for word replacement, it works like sed. e.g. for f in *Huge*; do mv $f ${f/Huge/Monstrous}; done
    – Eric
    Commented Feb 6, 2015 at 1:40
  • 1
    @Eric - I posted your answer as an alternative because I think it's more clear and elegant. If you also want to post it as an answer - I'll delete mine. Thanks!
    – Yehosef
    Commented Nov 25, 2015 at 15:23
  • Why the missing double quotes?
    – Wildcard
    Commented Dec 7, 2016 at 1:39
  • It gives me an error: "mv: target 'FILE_NAME' is not a directory"
    – Aubrey
    Commented May 2, 2017 at 13:32

this is really @Eric's answer from above - but it's an elegant answer so I'm reposting it as a proper answer to draw more attention to it.

for f in *Huge*; do mv "$f" "${f/Huge/Monstrous}"; done
( set -- "${path}/"${ptrn} ; for f ; do {
    echo "mv ${path}/${f} \
} ; done )

This should do the trick. Note - I'm not in the habit of handing over mass mv commands - as written it's just an echo. You'll have to sort that out before it'll work.


A simple native way to do it without looping, with directory traversal:

find -type f | xargs -I {} mv {} {}.txt

It will rename every file in place.

And below a working example with parallelization:

find -name "file*.p" | parallel 'f="{}" ; mv -- {} ${f:0:4}2503${f:8}'
  • It was a easy first approach to imagine better solution. If you want a working command do:
    – dtrckd
    Commented Dec 29, 2015 at 12:40
  • find -type f -name "file*.p" | parallel 'ext="{}" ; mv -- {} ${ext:0:4}2503${ext:8}'
    – dtrckd
    Commented Dec 29, 2015 at 12:41

If you find you do this sort of thing a lot, look up "rename.pl". It's a perl script, but allows you to simply feed it perl code (like a s/// expression), and it will do a mass rename based on that expression or code.

There's a basic version here: http://stackoverflow.org/wiki/Rename.pl but there are other versions floating around the net. It's been around for ages and ages and ages.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .