-1

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

report1.txt
report2.txt
report3.txt

How can I rename these so that they state

myreport1.txt
myreport2.txt
myreport3.txt

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 '21 at 18:06
  • Isn't mv used to move files? I only want to rename just those files using regular expressions. – Arsalan Feb 15 '21 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 '21 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 '21 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 '21 at 19:25
  • Regarding the duplicate, just use a pattern that matches your files in place of the * in the most voted on answer (for example report*.txt), then prepend my in place of Unix_. – Kusalananda Feb 15 '21 at 21:37

4 Answers4

3

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.

Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255
2

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)

xhienne
  • 17,793
  • 2
  • 53
  • 69
1

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

kasa
  • 99
1

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.

Kusalananda
  • 333,661