I have files in a directory. The file names are constructed using a date timestamp notation, the file names are of the form:


I want to rename all such files using the following naming convention:


I am not sure if I can use a command line utility like grep to do this, or if I need to write a bash script to do this.

Any help on how to solve this prob will be appreciated.

I am running on Ubuntu

  • 1
    There are batch file renaming utilities available through the Ubuntu software centre, have you tried any of these? – Tog Dec 10 '10 at 11:26
  • I don't know how to do it without a bash script – RobotHumans Dec 10 '10 at 11:30

A very simple way to do it

ls name* | while read a; do mv $a `echo $a | sed s/name_/name_20/`; done


ls name* | while read a; do mv $a $(echo $a | sed s/name_/name_20/); done

(since use of back-quotes is depreciated (or hard to read anyway))

it lists all files matching name_ then for each file it finds it replaces name_ with name_20. You can change 20 to 19 if you are working with files from the last millennium.

  • 'name' is a place holder. On my disk the files are named <name>_YYMM.csv, where <name> is an alphanumeric string. – Takashi Dec 10 '10 at 13:24
  • @Takashi - If <name> does not contain any underscores (_) it's still simple. Just substitute name_ for _ in the above example and replace ls name* with ls *.csv – Nifle Dec 10 '10 at 13:35
  • It worked! thanks. Now, ... to try to understand what kind of magic we are dealing with here ;) – Takashi Dec 10 '10 at 14:17
  • 1
    It would be better to use a for loop without ls. Variables that contain filenames (and, similarly, command substitution that processes filenames) should always be quoted. – Dennis Williamson Dec 10 '10 at 16:48

It is likely that you have a program or Perl script called rename on your system.

For the Perl script version:

rename 's/_/_20/' *_*.csv

For the util-linux-ng version:

rename _ _20 *_*.csv

Or, using Bash:

for f in name*; do mv "$f" "${f/_/_20}"; done

In zsh:

autoload zmv
zmv '(*_[0-9][0-9])([0-9][0-9].csv)' '${1}20${2}'

You can make the pattern less precise, e.g. '(*_??)(??.csv)' or even '(*)(??).csv' if there's no risk of other files matching.

If you don't want to use zsh, see Dennis Williamson's answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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