5887N/A#!/usr/bin/python2.7
5887N/A#
5887N/A# Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
5887N/A#
5887N/A# Permission is hereby granted, free of charge, to any person obtaining a
5887N/A# copy of this software and associated documentation files (the
5887N/A# "Software"), to deal in the Software without restriction, including
5887N/A# without limitation the rights to use, copy, modify, merge, publish,
5887N/A# distribute, and/or sell copies of the Software, and to permit persons
5887N/A# to whom the Software is furnished to do so, provided that the above
5887N/A# copyright notice(s) and this permission notice appear in all copies of
5887N/A# the Software and that both the above copyright notice(s) and this
5887N/A# permission notice appear in supporting documentation.
5887N/A#
5887N/A# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
5887N/A# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
5887N/A# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
5887N/A# OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
5887N/A# HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
5887N/A# INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
5887N/A# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
5887N/A# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
5887N/A# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
5887N/A#
5887N/A# Except as contained in this notice, the name of a copyright holder
5887N/A# shall not be used in advertising or otherwise to promote the sale, use
5887N/A# or other dealings in this Software without prior written authorization
5887N/A# of the copyright holder.
5887N/A#
5887N/A###########################################################################
5887N/A#
5887N/A
5887N/A
5887N/Aimport os, sys
5887N/Aimport getopt
5887N/Aimport fnmatch, re
5887N/A
5887N/Aclass Usage(Exception):
5887N/A def __init__(self, msg=None):
5887N/A if msg:
5887N/A self.msg = "Error: " + str(msg) + "\n\n"
5887N/A else:
5887N/A self.msg = ""
5887N/A self.msg = self.msg + "Usage: find_newer.py [options] dir...\n\n"
5887N/A self.msg = self.msg + "Options:\n"
5887N/A self.msg = self.msg + " --name glob find files matching glob\n"
5887N/A self.msg = self.msg + " --newer ref find files newer than a reference file"
5887N/A self.msg = self.msg + " -c compare ctimes (the time the file status was last changed)\n"
5887N/A self.msg = self.msg + " This is the default.\n"
5887N/A self.msg = self.msg + " -m compare mtimes (the time the file was last modified)\n"
5887N/A self.msg = self.msg + " -a compare atimes (the time the file was last accessed)\n"
5887N/A self.msg = self.msg + " -f follow symlinks\n"
5887N/A self.msg = self.msg + "\nNote: if more than one of -c -m and -a are specified, find_newer will\n"
5887N/A self.msg = self.msg + "compare the most recent of the given times\n"
5887N/A
5887N/A
5887N/Adef get_file_time(stat, type):
5887N/A time = None
5887N/A if "c" in type:
5887N/A time = stat.st_ctime;
5887N/A if "m" in type:
5887N/A if time:
5887N/A if time < stat.st_mtime:
5887N/A time = stat.st_mtime
5887N/A else:
5887N/A time = stat.st_mtime;
5887N/A elif "a" in type:
5887N/A if time:
5887N/A if time < stat.st_atime:
5887N/A time = stat.st_atime
5887N/A else:
5887N/A time = stat.st_atime;
5887N/A return time
5887N/A
5887N/Adirs_seen = []
5887N/Adef find_newer_files(dir, comp_time, ref_time, reobj, follow_links):
5887N/A dir = os.path.abspath(dir)
5887N/A if dir in dirs_seen:
5887N/A print >>sys.stderr, "Warning: infinite loop of symlinks"
5887N/A return
5887N/A dirs_seen.append(dir)
5887N/A for root, dirs, files in os.walk(dir):
5887N/A for file in files:
5887N/A try:
5887N/A file = os.path.abspath(os.path.join(root, file))
5887N/A stat = os.stat (file)
5887N/A if ref_time:
5887N/A if get_file_time (stat, comp_time) > ref_time:
5887N/A if reobj:
5887N/A if reobj.match (file):
5887N/A print file
5887N/A else:
5887N/A print file
5887N/A else:
5887N/A # no reference time, print all files that match the regex
5887N/A if reobj:
5887N/A if reobj.match (file):
5887N/A print file
5887N/A else:
5887N/A print file
5887N/A except:
5887N/A pass
5887N/A if follow_links:
5887N/A # descend into subdirectories that are really symlinks
5887N/A for d in dirs:
5887N/A d = os.path.join(root, d)
5887N/A if os.path.islink(d) and os.path.lexists(d):
5887N/A d = os.path.abspath(os.path.join(root, os.readlink(d)))
5887N/A find_newer_files(d, comp_time, ref_time, reobj, follow_links)
5887N/A
5887N/A
5887N/Adef main(argv=None):
5887N/A comp_time = []
5887N/A follow_links = False
5887N/A glob = None
5887N/A ref_file = None
5887N/A
5887N/A # parse the command line args
5887N/A if argv is None:
5887N/A argv = sys.argv
5887N/A try:
5887N/A try:
5887N/A opts, args = getopt.getopt(argv[1:], "hcmaf", ["help", "newer=", "name="])
5887N/A except getopt.error, msg:
5887N/A raise Usage(msg)
5887N/A for o, a in opts:
5887N/A if o == "-c":
5887N/A comp_time.append("c")
5887N/A elif o == "-m":
5887N/A comp_time.append("m")
5887N/A elif o == "-a":
5887N/A comp_time.append("a")
5887N/A elif o in ("-h", "--help"):
5887N/A raise Usage()
5887N/A elif o in "-f":
5887N/A follow_links = True
5887N/A elif o in "--name":
5887N/A glob = a
5887N/A elif o in "--newer":
5887N/A ref_file = a
5887N/A if len(args) < 1:
5887N/A raise Usage("invalid arguments")
5887N/A
5887N/A except Usage, err:
5887N/A print >>sys.stderr, err.msg
5887N/A print >>sys.stderr, "Use --help for usage information"
5887N/A return 2
5887N/A
5887N/A # default: compare ctime
5887N/A if not comp_time:
5887N/A comp_time = ["c"]
5887N/A
5887N/A # return stat time as floats
5887N/A os.stat_float_times (True)
5887N/A
5887N/A if ref_file:
5887N/A try:
5887N/A ref_stat = os.stat(ref_file)
5887N/A except:
5887N/A print >>sys.stderr, "Cannot stat reference file: %s" % ref_file
5887N/A return 1
5887N/A ref_time = get_file_time (ref_stat, comp_time)
5887N/A else:
5887N/A ref_time = None
5887N/A
5887N/A for dir in args:
5887N/A if not os.path.isdir(dir):
5887N/A print >>sys.stderr, "Directory not found: %s" % dir
5887N/A return 1
5887N/A
5887N/A if glob:
5887N/A regex = fnmatch.translate(glob)
5887N/A reobj = re.compile (regex)
5887N/A else:
5887N/A reobj = None
5887N/A
5887N/A find_newer_files(dir, comp_time, ref_time, reobj, follow_links)
5887N/A
5887N/Aif __name__ == "__main__":
5887N/A sys.exit(main())