#! /usr/bin/env python
import sys, os, fnmatch, codecs, argparse
from os.path import join, relpath
from itertools import chain
from zipfile import ZipFile, ZIP_DEFLATED

def flatten(iterable):
    return list(chain(*iterable))

def make_file_list(args, dirname, names):
    file_list, exclude = args

    # Match names against each line of exclude then flatten the result then
    # remove them from the walk
    for n in flatten([fnmatch.filter(names, x) for x in exclude]):
        if n in names: del names[names.index(n)]

    # Record files that aren't directories
    file_list[dirname] = [n for n in names if not os.path.isdir(join(dirname, n))]

def prepend_files(header, file_list, targets):
    with codecs.open(header, 'r', 'utf-8-sig') as h: head = h.read()

    for path, files in file_list.iteritems():
        # Find targets in files and prepend the header
        for f in flatten([fnmatch.filter(files, t) for t in targets]):
            fp = relpath(join(path, f))
            print "Prepending header to", fp
            with codecs.open(fp, 'r+', 'utf-8-sig') as tf:
                orig = tf.read()
                tf.seek(0)
                tf.write(head + orig)

def compress_files(file_list, zipfile):
    with ZipFile(zipfile, 'w', ZIP_DEFLATED) as zf:
        for path, files in file_list.iteritems():
            map(lambda f: zf.write(join(relpath(path), f)), files)

        print "Created", zipfile

def process(dir, file, exclude, target, compress, prepend):
    file_list = {}

    # Make sure we use absolute path since zip filename depends on basename
    dir = os.path.abspath(dir)

    # Some programs apparently always prepend content with BOM ...
    with codecs.open(exclude, 'r', 'utf-8-sig') as f:
        exclude = [l.rstrip(os.linesep + os.path.sep) for l in f.readlines()]

    os.path.walk(dir, make_file_list, (file_list, exclude))

    # Add file to files
    if prepend == 'yes': prepend_files(file, file_list, target)

    # Zip it up!
    if compress == 'yes': compress_files(file_list, os.path.basename(dir) + '.zip')

def main(argv):
    parser = argparse.ArgumentParser(description='''Add a header to files and
            zip them up.''')
    parser.add_argument('-e', '--exclude',
            default='exclude.txt', metavar='EXCLUDE',
            help='a file containing globs to be excluded from processing; defaults to "exclude.txt"')
    parser.add_argument('-f', '--file',
            default='header.txt', metavar='FILE',
            help='a file whose contents will be prepended to target files; defaults to "header.txt"')
    parser.add_argument('-c', '--compress',
            choices=['yes', 'no'], default='yes',
            help='compress non-excluded files into a zip-file; defaults to "yes"')
    parser.add_argument('-p', '--prepend',
            choices=['yes', 'no'], default='yes',
            help='whether header (FILE) should be prepended to target files; defaults to "yes"')
    parser.add_argument('dir',
            help='directory in which to search for target files')
    parser.add_argument('target', nargs='*',
            help='files to target, e.g. "*.cs" or "*.c *.h"')

    process(**vars(parser.parse_args()))

if __name__ == '__main__':
    main(sys.argv)


@@ -571,30 +571,33 @@
    f
-ile_list%5B
+or f in %5Bjoin(
 dirname
-%5D = %5Bn
+, n)
  for
@@ -647,16 +647,45 @@
 me, n))%5D
+:%0A        file_list.append(f)
 %0A%0Adef pr
@@ -799,58 +799,8 @@
 ()%0A%0A
-    for path, files in file_list.iteritems():%0A    
     
@@ -846,28 +846,24 @@
  header%0A    
-   
- 
 for f in fla
@@ -887,17 +887,21 @@
 ter(file
-s
+_list
 , t) for
@@ -921,52 +921,8 @@
 %5D):%0A
-            fp = relpath(join(path, f))%0A    
     
@@ -959,15 +959,19 @@
 o%22, 
-fp%0A    
+relpath(f)%0A
     
@@ -992,17 +992,16 @@
 s.open(f
-p
 , 'r+', 
@@ -1032,20 +1032,16 @@
         
-    
 orig = t
@@ -1061,20 +1061,16 @@
         
-  
-  
 tf.seek(
@@ -1072,20 +1072,16 @@
 seek(0)%0A
-    
         
@@ -1215,19 +1215,9 @@
 for 
-path, files
+f
  in 
@@ -1229,20 +1229,8 @@
 list
-.iteritems()
 :%0A  
@@ -1242,22 +1242,8 @@
     
- map(lambda f:
  zf.
@@ -1252,21 +1252,16 @@
 ite(
-join(
 relpath(
 path
@@ -1260,25 +1260,10 @@
 ath(
-path), f)), files
+f)
 )%0A%0A 
@@ -1375,10 +1375,10 @@
 t = 
-%7B%7D
+%5B%5D
 %0A%0A  

Use a list instead of a dict.