Last active
October 4, 2015 05:36
-
-
Save craigpalermo/7ad80bb04bd8b55243b1 to your computer and use it in GitHub Desktop.
A script that moves all files in current directory that haven't been modified in the desired number of days to a different folder.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from datetime import datetime, timedelta | |
from sets import Set | |
import argparse | |
import sys | |
import os | |
import time | |
import shutil | |
import re | |
# BEGIN CONFIGURATION | |
conf_days=14 | |
conf_destination="./Archive" | |
conf_ignored_extensions= Set([".key", ".kdbx"]) | |
# END CONFIGURATION | |
def input_is_valid(days): | |
""" | |
Returns True if each function argument provided is valid. If an argument | |
is invalid, prints description of error and then returns False. | |
""" | |
is_valid = True | |
if days and not (is_integer(days) and days >= 0): | |
is_valid = False | |
print("'{}' is not a valid number of days.".format(days)) | |
return is_valid | |
def calculate_start_date(arg_days): | |
""" | |
Returns the result of subtracting the time delta of the given arguments | |
from the current datetime. | |
""" | |
days = arg_days if arg_days else conf_days | |
result = datetime.now() - timedelta(days=int(days)) | |
return result | |
def move_files(before_date, preview=False, arg_destination=None): | |
""" | |
Attempts to move all files (not folders) in current directory that were | |
last modified before 'before_date'. Returns the number of files affected. | |
""" | |
def log_to_console(action, description): | |
action = action.capitalize() if action else action | |
print("{}: {}".format(action, description)) | |
dest = arg_destination if arg_destination else conf_destination | |
change_count = 0 | |
for filename in os.listdir('.'): | |
if os.path.isfile(filename) and filename != os.path.basename(__file__): | |
# get time file was last modified | |
file_ctime = datetime.fromtimestamp(os.path.getctime(filename)) | |
# get file extension | |
match = re.search(r".+([.][\w]+)", filename) | |
if match: | |
file_extension = match.group(1) | |
# move file if applicable | |
if file_ctime < before_date: | |
dest_path = "{}/".format(os.path.abspath(dest), filename) | |
try: | |
description = "{} ({})".format(filename, shorten_date(file_ctime)) | |
if (match and file_extension not in conf_ignored_extensions) or not match: | |
if preview: | |
log_to_console("will move:", description) | |
else: | |
shutil.move(os.path.abspath(filename), dest_path) | |
log_to_console("moved", description) | |
change_count += 1 | |
except shutil.Error as e: | |
log_to_console("unable to move", description) | |
return change_count | |
# helper functions | |
def is_integer(s): | |
""" | |
Returns True if 's' is an integer, and False otherwise. | |
""" | |
try: | |
return (float(s) and float(s) % 1 == 0) | |
except ValueError: | |
return False | |
def shorten_date(date): | |
""" | |
Returns date as string formatted like Jan 01, 2015, or empty string | |
if date given is invalid. | |
""" | |
try: | |
result = date.strftime("%b %d, %Y") if date else "" | |
except Exception: | |
result = "" | |
return result | |
def main(argv=None): | |
# parse command line arguments | |
parser = argparse.ArgumentParser(description='Process some integers.') | |
parser.add_argument( | |
'--days', | |
dest='days', | |
action='store', | |
help='max age of files to archive in days' | |
) | |
parser.add_argument( | |
'--preview', | |
dest='preview', | |
action='store_true', | |
help='view list of affected files without actually moving anything' | |
) | |
args = parser.parse_args() | |
# exit if invalid input detected | |
if not input_is_valid(args.days): | |
return | |
# calculate max retention cutoff date | |
cutoff_date = calculate_start_date(args.days) | |
print("Archiving files last modified before {}.".format(shorten_date(cutoff_date))) | |
print("Ignored extensions: {}".format(list(conf_ignored_extensions))) | |
# move applicable files | |
affected_count = move_files(cutoff_date, preview=args.preview) | |
print("Files affected: {}".format(affected_count)) | |
if __name__ == "__main__": | |
sys.exit(main()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment