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