10

I have a large number of folders, named as dates like so:

10 Aug 2010  15 Sep 2010  20 Jun 2010  25 Jul 2010  6 Nov 2010
10 Sep 2010  16 Aug 2010  20 Mar 2010  26 Aug 2010  6 Oct 2010
11 Apr 2010  16 Jun 2010  21 Jun 2010  28 Aug 2010  7 Apr 2010
12 Aug 2010  16 Oct 2010  21 Mar 2010  28 Feb 2010  7 Aug 2010
13 May 2010  17 Apr 2010  22 Feb 2010  28 Jun 2010  7 Jun 2010
14 Aug 2010  17 Aug 2010  23 Jul 2010  28 Mar 2010  8 Apr 2010
14 Jun 2010  18 Aug 2010  24 Jul 2010  29 Mar 2010  8 Aug 2010
15 Aug 2010  19 Aug 2010  24 Nov 2010  30 Aug 2010  8 Jul 2010
15 Jul 2010  4 Apr 2010  25 Apr 2010  6 May 2010   8 Sep 2010

I want the date format to change to this:

2010-04-04  2010-05-03
2010-06-06  2010-07-02
2010-07-05  2010-09-01
2010-09-04  2010-09-05
2010-11-01

How can I batch rename a lot of folders from DD MMM YYYY to YYYY-MM-DD?

5 Answers 5

12

Somewhat to my own surprise, it looks like our old friend prename (a.k.a rename on some systems) can do that - with a little wrangling:

$ prename -vn -- '
  BEGIN{use Time::Piece};
  s/\d+ \w+ \d+/Time::Piece->strptime($&, "%d %b %Y")->strftime("%Y-%m-%d")/e
' *
10 Aug 2010 renamed as 2010-08-10
8 Sep 2010 renamed as 2010-09-08

Alternatively, using GNU date

dirs=( ?\ ???\ ???? ??\ ???\ ???? ) # matches D MMM YYYY and DD MMM YYYY

for d in "${dirs[@]}"; do mv -v -- "$d" "$(date '+%Y-%m-%d' -d "$d")"; done

Testing with an echo (equivalent to prename's -n flag):

$ for d in "${dirs[@]}"; do echo mv -v -- "$d" "$(date '+%Y-%m-%d' -d "$d")"; done
mv -v -- 8 Sep 2010 2010-09-08
mv -v -- 10 Aug 2010 2010-08-10

Note that parsing of dates can be locale dependent.

9

The GNU date command is very good at converting between different date formats. For example:

$ date -d '17 Aug 2010' +%F
2010-08-17

With that in mind, if the only things in your target directory are the subdirectories you want to rename, you can simply do:

for d in *; do mv "$d" "$(date -d "$d" +%F)"; done

If you want to specify directories only, use:

for dir in */; do d=${dir%%/}; mv "$d" "$(date -d "$d" +%F)"; done

And to match only directories whose name starts with a number:

for dir in [0-9]*/; do d=${dir%%/}; mv "$d" "$(date -d "$d" +%F)"; done
6

Here is a Python script that can do the renaming using the datetime module:

#!/usr/bin/env python

from datetime import datetime
import os
import os.path
import sys


def main(target):
    dir_path = os.path.abspath(target)
    for i in os.listdir(target):
        old_name = os.path.join(dir_path, i)
        d = datetime.strptime(i, '%d %b %Y').strftime('%Y-%m-%d')
        new_name = os.path.join(dir_path, d)
        os.rename(old_name, new_name)

if __name__ == '__main__':
    main(sys.argv[1])

Let's call the script rename.py. To use the script, first make it executable by running chmod +x rename.py and then running ./rename.py parent_dir where parent_dir is the parent directory containing all the directories whose names you want to change.

4

Here is a Ruby script that does this same thing. Put this into the directory where all those directory resides.

#!/usr/bin/env ruby

require 'time'

Dir.glob('*').select do |f|
    if File.directory? f
        time = Time.parse(f.to_s)
        File.rename(f, time.strftime("%Y-%m-%d"))
    end
end

Use chmod +x rename.rb and ./rename.rb to rename the directories

0

if you want a good GUI solution try pyrenamer easy and very configurable

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.