Skip to content

Instantly share code, notes, and snippets.

@tcely
Last active June 11, 2017 00:20
Show Gist options
  • Save tcely/748e3e2f4f9731cf2c860c75760bf3f5 to your computer and use it in GitHub Desktop.
Save tcely/748e3e2f4f9731cf2c860c75760bf3f5 to your computer and use it in GitHub Desktop.
A better touch than provided by busybox
#!/usr/bin/env python
import io, os, sys
from argparse import ArgumentParser
from calendar import timegm
from time import gmtime, localtime, mktime, strftime, strptime
def touchUTCString(t):
return timegm(strptime(t, '%a, %d %b %Y %H:%M:%S %Z'))
def touchTimeSpec(t):
r = None
try:
r = mktime(strptime(t, '%Y%m%d%H%M.%S'))
except ValueError:
r = mktime(strptime(t, '%Y%m%d%H%M'))
return r
parser = ArgumentParser(add_help=False)
parser.add_argument('--help', action='help')
group = parser.add_mutually_exclusive_group()
group.add_argument('-a', action='store_true')
group.add_argument('-m', action='store_true')
parser.add_argument('-c', action='store_true')
# Python 2.7 os.utime won't operate on symlinks
# This is here for -r only at this point.
parser.add_argument('-h', action='store_true')
group = parser.add_mutually_exclusive_group()
group.add_argument('-r', metavar='FILE')
group.add_argument('-d', metavar='DATETIME', type=touchUTCString)
group.add_argument('-t', metavar='CCYYMMDDhhmm[.ss]', type=touchTimeSpec)
parser.add_argument('files', nargs='+', metavar='FILE')
def addtimes(args):
args.atime = None
args.mtime = None
if args.r:
if args.h:
stat = os.lstat
else:
stat = os.stat
try:
stats = stat(args.r)
args.atime = stats.st_atime
args.mtime = stats.st_mtime
except:
pass
elif args.t:
args.atime = args.t
args.mtime = args.t
elif args.d:
args.atime = args.d
args.mtime = args.d
def touch(path, atime=None, mtime=None):
global args
if args.h:
exists = os.path.lexists
stat = os.lstat
# -h doesn't create either
if not (exists(path) and os.path.exists(path)):
return False
# Python 2.7 os.utime doesn't work on links.
stat = os.stat
else:
exists = os.path.exists
stat = os.stat
if args.c and not exists(path):
return True
if args.a:
atime = mktime(localtime())
mtime = None
if args.m:
atime = None
mtime = mktime(localtime())
with io.open(path, 'ab'):
if atime or mtime:
stats = stat(path)
utimes = (atime or stats.st_atime, mtime or stats.st_mtime)
else:
utimes = None
os.utime(path, utimes)
return True
if '__main__' == __name__:
args = parser.parse_args()
addtimes(args)
allok = True
for file in args.files:
allok = touch(file, args.atime, args.mtime) and allok
if not allok:
sys.exit(1)
sys.exit(0)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment