Last active
October 6, 2016 13:37
-
-
Save wlupton/e9f698cb39b73306e772 to your computer and use it in GitHub Desktop.
Update directory modification times based on modification times of non-directories in sub-tree
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
#!/usr/bin/env python3 | |
"""Scan the files in a directory sub-tree and set directory modification times | |
to be the modification time of the newest non directory file within the | |
sub-tree. This is work around the Office 2016 practice of creating a temporary | |
file in the same directory as each file when opening that file (which of | |
course updates the directory modification time.""" | |
import argparse, os, sys, time | |
loglevel = 1 | |
def scan_directory(dirpath, mtimes={}, level=0): | |
"""Scan directory sub-tree... | |
dirpath: root of directory sub-tree | |
mtimes: dictionary... | |
level: indentation level (used only for reporting)""" | |
mtime0 = os.stat(dirpath).st_mtime | |
mtimes[dirpath] = {"mtime0": mtime0, "mtime": 0.0} | |
for direntry in os.scandir(dirpath): | |
name = direntry.name | |
path = direntry.path | |
is_file = direntry.is_file() | |
is_dir = direntry.is_dir() | |
is_symlink = direntry.is_symlink() | |
if loglevel > 2: | |
print("%s%s %s" % (level * " ", name, | |
time.ctime(direntry.stat().st_mtime))) | |
if not is_file and not is_dir: | |
continue | |
if is_dir and name == ".git": | |
continue | |
if not is_dir and name == ".DS_Store": | |
continue | |
if is_dir and not is_symlink: | |
mtime = scan_directory(path, level=level+1, mtimes=mtimes) | |
else: | |
mtime = direntry.stat().st_mtime | |
if mtime > mtimes[dirpath]["mtime"]: | |
mtimes[dirpath]["mtime"] = mtime | |
return mtimes[dirpath]["mtime"] | |
def main(argv=None): | |
"""Main program.""" | |
if argv is None: argv = sys.argv | |
# XXX might be better to use positional argument for directory? | |
global loglevel | |
parser = argparse.ArgumentParser( | |
prog=argv[0], description="update directory modification time") | |
parser.add_argument("-d", "--directory", | |
help="root of directory sub-tree; default is current directory") | |
parser.add_argument("-l", "--loglevel", type=int, | |
help="logging level; default: %d" % loglevel) | |
parser.add_argument("-n", "--dryrun", action="store_true", | |
help="dry run; report what would have been done but don't do it") | |
args = parser.parse_args(argv[1:]) | |
directory = args.directory if args.directory else os.getcwd() | |
dryrun = args.dryrun | |
if args.loglevel is not None: loglevel = args.loglevel | |
mtimes = {} | |
scan_directory(directory, mtimes) | |
for dirname in sorted(mtimes.keys()): | |
mtime0 = mtimes[dirname]["mtime0"] | |
mtime = mtimes[dirname]["mtime"] | |
if mtime > 0 and mtime < mtime0: | |
if loglevel > 0: | |
print("%s: %s -> %s" % (dirname, time.ctime(mtime0), | |
time.ctime(mtime))) | |
if dryrun or loglevel > 1: | |
print("os.utime(\"%s\", (%d, %d))" % (dirname, mtime, mtime)) | |
if not dryrun: | |
os.utime(dirname, (mtime, mtime)) | |
if __name__ == "__main__": | |
sys.exit(main()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I created this script in frustration at Word's habit of creating a temporary file in the same directory as the open document, which updates the directory modification time even though nothing has really changed.