#!/usr/bin/env python import argparse import fnmatch import os import sys # Recursively generate index.html files for # all subdirectories in a directory tree index_file_name = 'index.html' CSS = """ """ def process_dir(top_dir, opts): for parentdir, dirs, files in os.walk(unicode(top_dir)): if not opts.dryrun: index_file = open(os.path.join(parentdir, index_file_name), "w") index_file.write(''' {css}

{curr_dir}

  • '''.format( css=CSS, curr_dir=os.path.basename(os.path.abspath(parentdir).encode('utf8')) ) ) for dirname in sorted(dirs): absolute_dir_path = os.path.join(parentdir, dirname) if not os.access(absolute_dir_path, os.W_OK): print("***ERROR*** folder {} is not writable! SKIPPING!".format(absolute_dir_path)) continue if opts.verbose: print('DIR:{}'.format(absolute_dir_path)) if not opts.dryrun: index_file.write("""
  • 📁 {link_text}
  • """.format( link=dirname.encode('utf8'), link_text=dirname.encode('us-ascii', 'xmlcharrefreplace'))) for filename in sorted(files): if opts.filter and not fnmatch.fnmatch(filename, opts.filter): if opts.verbose: print('SKIP: {}/{}'.format(parentdir, filename)) continue if opts.verbose: print('{}/{}'.format(parentdir, filename)) filename_escaped = filename.encode('us-ascii', 'xmlcharrefreplace') filename_utf8 = filename.encode('utf8') if filename.strip().lower() == index_file_name.lower(): continue try: size = int(os.path.getsize(os.path.join(parentdir, filename))) if not opts.dryrun: index_file.write( """
  • 📄 {link_text}{size}
  • """.format( link=filename_utf8, link_text=filename_escaped, size=pretty_size(size)) ) except Exception as e: print('ERROR writing file name:', e) print('filename_utf8:') repr(filename_utf8) print('filename_escaped:'), repr(filename_escaped) if not opts.dryrun: index_file.write("""
    """) index_file.close() # bytes pretty-printing UNITS_MAPPING = [ (1024 ** 5, ' PB'), (1024 ** 4, ' TB'), (1024 ** 3, ' GB'), (1024 ** 2, ' MB'), (1024 ** 1, ' KB'), (1024 ** 0, (' byte', ' bytes')), ] def pretty_size(bytes, units=UNITS_MAPPING): """Human-readable file sizes. ripped from https://pypi.python.org/pypi/hurry.filesize/ """ for factor, suffix in units: if bytes >= factor: break amount = int(bytes / factor) if isinstance(suffix, tuple): singular, multiple = suffix if amount == 1: suffix = singular else: suffix = multiple return str(amount) + suffix if __name__ == "__main__": parser = argparse.ArgumentParser(description='''DESCRIPTION: Generate directory index files recursively. Start from current dir or from folder passed as first positional argument. Optionally filter by file types with --filter "*.py". ''') parser.add_argument('top_dir', nargs='?', action='store', help='top folder from which to start generating indexes, ' 'use current folder if not specified', default=os.getcwd()) parser.add_argument('--filter', '-f', help='only include files matching glob', required=False) parser.add_argument('--verbose', '-v', action='store_true', help='***WARNING: this can take a very long time with complex file tree structures***' ' verbosely list every processed file', required=False) parser.add_argument('--dryrun', '-d', action='store_true', help="don't write any files, just simulate the traversal", required=False) config = parser.parse_args(sys.argv[1:]) process_dir(config.top_dir, config)