Instantly share code, notes, and snippets.

Embed
What would you like to do?
watch-cp - monitors files for changes and copies again if changes occur
#!/usr/bin/env python
'''
Script that functions a bit like standard cp (copy),
but monitors source files for changes and copies them
again if they change.
'''
import sys
import os
import os.path
import time
import shutil
from optparse import OptionParser
def watch_and_copy(sources, target, recursive=False):
mod_times = {}
def copy(src, target):
src = os.path.abspath(src)
mtime = mod_times.get(src, 0)
cur_mtime = os.stat(src).st_mtime
if cur_mtime > mtime:
if mtime != 0:
print '%s changed' % src
parent = os.path.dirname(target)
if not os.path.exists(parent):
os.makedirs(parent)
shutil.copy(src, target)
mod_times[src] = cur_mtime
def copydir(src, target):
src = os.path.abspath(src)
parent = os.path.dirname(src)
for dirpath, dirnames, filenames in os.walk(src):
prefix = os.path.commonprefix([parent, dirpath])
reldirpath = dirpath[len(prefix):]
if reldirpath.startswith(os.sep):
reldirpath = reldirpath[len(os.sep):]
for filename in filenames:
sourcepath = os.path.join(dirpath, filename)
targetpath = os.path.join(target, reldirpath, filename)
copy(sourcepath, targetpath)
while True:
for src in sources:
if os.path.isdir(src):
copydir(src, target)
else:
copy(src, target)
time.sleep(0.5)
def main():
usage = \
'usage: %prog [options] SOURCE DEST\n' + \
' or: %prog [options] SOURCE... DIRECTORY'
parser = OptionParser(usage=usage)
parser.add_option("-r", action="store_true", dest="recursive",
default=False, help="copy recursively")
options, args = parser.parse_args()
if len(args) < 2:
parser.print_help()
sys.exit(1)
source = args[:-1]
target = args[-1]
# if we are not copying into a directory
# we can only have one source file
if not os.path.isdir(target):
if len(source) != 1:
parser.print_help()
sys.exit(1)
if not options.recursive:
for src in source:
if os.path.isdir(src):
parser.print_help()
sys.exit(1)
try:
watch_and_copy(source, target, recursive=options.recursive)
except KeyboardInterrupt:
pass
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment