I have a bunch of files and I want to rename them using regular expressions. I want to do this in a Linux Command line.

I have the files


How can I rename these so that they state


Please let me know, I've searched the internet and they have many complex examples.

  • 1
    It would be interesting to know why you want to use regular expressions. Also, are those the only files you have, or do you want to rename all file that have names ending in .txt, or that start with report, or just any file that happens to occur in the current directory. If only those three files, then mv report1.txt myreport1.txt; mv report2.txt myreport2.txt; mv report3.txt myreport3.txt would do it. How would you want to handle name clashes (one or more of the target names already existing, possibly as a directory)? – Kusalananda Feb 15 at 18:06
  • Isn't mv used to move files? I only want to rename just those files using regular expressions. – Arsalan Feb 15 at 18:32
  • 2
    Renaming a file is done by moving it to a new name. It's unclear why you think you need to use regular expressions. You may possibly want to use globbing pattern to select the files to process, but there's certainly no need to use a regular expression here. Regular expressions are most commonly used for matching in text, and filenames are not text in that same sense (for one, they can't contain /, but may contain newlines, which lines in a text can't contain). – Kusalananda Feb 15 at 18:45
  • 1
    Arslan: Kusalananda has asked you relevant questions, which you don't seem keen to answer. Help us help you. – Quasímodo Feb 15 at 18:50
  • Try rename report myreport report[123].txt (not tested). This also addresses your aversion of for loops and complexity. – berndbausch Feb 15 at 19:25

To answer OP's question in comment: "Is there a way to do it without using a for loop?"

I usually use a dedicated utility for this: mmv

mmv 'report?.txt' 'myreport#1.txt'

(there are several other similar tools around, like rename)

  • Thanks, this is what I was looking for. – Arsalan Feb 15 at 21:56

You can use just a simple loop in one line:

for ftr in report[0-9]*.txt; do mv "$ftr" "my${ftr}"; done

If you don't want use a loop, you can try this:

find . -maxdepth 1 -type f -name "report[0-9]*.txt" -printf "%f\n" | xargs -I{} mv {} my{}

Note that, as in the for loop, you need to put this in the path where the files are.


In the zsh shell, the following would rename the three files shown:

autoload -U zmv
zmv -v -- 'report<1-3>.txt' 'my$f'

The source pattern should be a valid zsh extended globbing pattern (quoted), and the source pattern used here simply matches the three filenames that you mentioned.

The $f in the target pattern will be replaced by the full original filename. One could also use $1, $2, etc. to refer to any parenthesized capture groups in the source pattern (there are none used here as it's not needed).

From the bash shell (passing the source and target patterns to the zsh -c shell as arguments):

zsh -c 'autoload -U zmv; zmv -v -- $1 $2' zsh 'report<1-3>.txt' 'my$f'

This answer ignores the issue of name collisions.


You can use mv:

for f in *.txt;do mv $f  "my$f"; done

Or you can use rename: you may need to install it based on your distro.

rename -v -n 's/report/myreport/' *.txt

rename (option*) 's/oldname/newname/' file1 file2 or use *.extension

If you are on Archlinux use this if that didn't work:

rename -v report myreport *.txt

For options check man rename

  • The first variation is a broken variant of the answer that mondo-cane gave. – Kusalananda Feb 15 at 18:57
  • @ Kusalananda I am not here to argue but for mondo-cane it seems the time "answered 2 hours ago". However, we are here to help I am not to Compete. – kasa Feb 15 at 20:58

Not the answer you're looking for? Browse other questions tagged or ask your own question.