Don't like ads? PRO users don't see any ads ;-)
Guest

Untitled

By: a guest on Apr 15th, 2012  |  syntax: None  |  size: 2.80 KB  |  hits: 10  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. #!/usr/bin/env python
  2. #
  3. # Python script to facilitate the hardlinking of directories and their files.
  4.  
  5. import sys
  6. if sys.version_info < (2, 3):
  7.     raise RuntimeError('Python 2.3+ is required.')
  8.  
  9. import logging
  10. import optparse
  11. import os
  12.  
  13. version = '\nhardlinkify-1.0 - by Jake Wharton <jakewharton@gmail.com>\n'
  14.  
  15. #CLI argument parser
  16. parser = optparse.OptionParser(usage='Usage: %prog [options] source [source ...] destination', version=version)
  17. parser.add_option('-d', '--debug', dest='is_debug', action='store_true', default=False, help='print detailed execution information')
  18. parser.add_option('-q', '--quiet', dest='is_quiet', action='store_true', default=False, help='no output except warnings and errors')
  19. options, targets = parser.parse_args()
  20.  
  21. #Print version if not quiet
  22. if not options.is_quiet:
  23.     parser.print_version()
  24.  
  25. #Logging setup
  26. level = logging.INFO
  27. if options.is_quiet:
  28.     level = logging.WARN
  29. if options.is_debug:
  30.     level = logging.DEBUG
  31. logging.basicConfig(format='%(asctime)s %(levelname)-7s %(message)s')
  32. logger = logging.getLogger(os.path.basename(__file__))
  33. logger.setLevel(level)
  34.  
  35. #Error checking
  36. if options.is_quiet and options.is_debug:
  37.     logger.warn('Options --quiet and --debug are mutually exclusive. Ignoring --quiet.')
  38. if len(targets) < 2:
  39.     logger.error('You must specify at least one source and the destination.')
  40.     sys.exit(1)
  41.  
  42.  
  43. def link(file=None, dest=None, unroll=False):
  44.     if file is None:
  45.         raise ValueError('File parameter is required.')
  46.     if dest is None:
  47.         raise ValueError('Destination parameter is required.')
  48.  
  49.     if not os.path.exists(file):
  50.         logger.warn('File "%s" does not exist. Skipping.', file)
  51.         return
  52.     elif os.path.isdir(file):
  53.         if unroll:
  54.             logger.debug('Unrolling directory "%s" in "%s".', file, dest)
  55.         new_dest = dest if unroll else os.path.join(dest, os.path.basename(file))
  56.         for new_file_name in os.listdir(file):
  57.             new_file = os.path.join(file, new_file_name)
  58.             logger.debug('> link("%s", "%s")', new_file, new_dest)
  59.             link(new_file, new_dest)
  60.         return
  61.  
  62.     if not os.path.exists(dest):
  63.         logger.info('Directory "%s" does not exist. Creating.', dest)
  64.         os.makedirs(dest)
  65.  
  66.     new_file = os.path.join(dest, os.path.basename(file))
  67.  
  68.     if os.path.exists(new_file):
  69.         logger.warn('File "%s" already exists. Skipping.', new_file)
  70.         return
  71.  
  72.     logger.info('Linking "%s" to "%s"...', new_file, file)
  73.     os.link(file, new_file)
  74.  
  75.  
  76. #Get arguments and perform linking
  77. destination = os.path.abspath(targets[-1])
  78. logger.debug('Destination: %s', destination)
  79. files = [os.path.abspath(file) for file in targets[:-1]]
  80. for file in files:
  81.     logger.debug('File: %s', file)
  82. for file in files:
  83.     logger.debug('> link("%s", "%s")', file, destination)
  84.     link(file, destination, True)