blob: 319192fc34353678c598cb5417f9882daa238ec6 [file] [log] [blame]
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at
import datetime
from optparse import OptionParser
import os
import re
import stat
def organize(basedir):
""" This function organizes a directory of files by moving files that contain
a date string in the format YYYY-MM-DD(-HH) into child directories of the format
YYYY/MM/YYYY-MM-DD(-HH)/file, and creating top-level symlinks to the most recent
30 days of directories. It also creates a 'latest' symlink to point to the most
recent date directory.
# Generate a list of top-level symlink dirs, and files that need to be
# moved into date-specific directories.
files_to_move = []
symlink_dirs = []
date_regex = '(\d{4}-\d{2}-\d{2})(-\d{2})?'
date_re = re.compile(date_regex)
for item in os.listdir(basedir):
m =
if m:
if os.path.isfile(item) and not os.path.islink(item):
date =
short_filename = re.sub('[_-]?' + date_regex, '', item)
files_to_move.append((item, date, short_filename))
elif os.path.isdir(item) and os.path.islink(item):
# Create new directories for dates that don't have them, and
# corresponding top-level symlinks; move files into date-specific
# directories.
perms = stat.S_IRWXU | stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH
for (filename, date, short_filename) in files_to_move:
date_parts = date.split('-')
directory = os.path.join(date_parts[0], date_parts[1], date)
if date not in symlink_dirs:
if not os.access(directory, os.F_OK):
# make sure all our directories have correct perms
os.chmod(date_parts[0], perms)
os.chmod(os.path.join(date_parts[0], date_parts[1]), perms)
os.chmod(directory, perms)
if not os.path.islink(date):
os.symlink(directory, date)
os.rename(filename, os.path.join(directory, filename))
short_symlink = os.path.join(directory, short_filename)
if os.path.exists(short_symlink) and os.path.islink(short_symlink):
if not os.path.exists(short_symlink):
os.symlink(filename, short_symlink)
# Delete any top-level symlinks that are > 30 days old
for symlink in symlink_dirs:
m ='(\d{4})-(\d{2})-(\d{2})', symlink)
if m:
link_date =,
datediff = - link_date
if datediff.days > 30:
# Find the newest symlink and create a 'latest' symlink to the directory
# it points to.
if os.access('latest', os.F_OK):
newest_symlink = None
for symlink in symlink_dirs:
if not newest_symlink or symlink > newest_symlink:
newest_symlink = symlink
if newest_symlink:
date_parts = newest_symlink.split('-')
directory = os.path.join(date_parts[0], date_parts[1], newest_symlink)
os.symlink(directory, 'latest')
if __name__ == "__main__":
parser = OptionParser()
parser.add_option('--directory', dest='basedir', action='store',
help='base directory to organize')
options, args = parser.parse_args()