1. Instant Arch
  2. Untitled project
  3. pp

Commits

Josh VanderLinden  committed e5ce333

Allowing globbing to get copy progress for multiple files

  • Participants
  • Parent commits 10fcb7e
  • Branches master

Comments (0)

Files changed (2)

File PKGBUILD

View file
  • Ignore whitespace
 # Maintainer: Josh VanderLinden <arch@cloudlery.com>
 pkgname=pp-git
 pkgver=20121030
-pkgrel=3
+pkgrel=4
 pkgdesc="Simple wrapper around dd to show approximate progress during a dump"
 arch=('any')
 url="https://gist.github.com/3963262"

File pp.py

View file
  • Ignore whitespace
 #!/usr/bin/env python2
 
+from glob import iglob
 from subprocess import Popen, PIPE, call
 import logging
 import math
 
     def __init__(self):
         self.pipe = None
-        self.filesize = None
+        self.multifile = False
+        self.of_base = None
 
     def __call__(self, oflag=None, **kwargs):
         if oflag is None:
             log.info('Inserting oflag=direct,sync as an argument for more accurate progress')
             kwargs['oflag'] = 'direct,sync'
 
-        # get some information about the source file
+        # get some information about the source file(s)
         try:
             input_file = kwargs['if']
         except KeyError:
             log.error('Invalid input file')
             sys.exit(1)
 
+        all_files = list(iglob(input_file))
+        self.multifile = len(all_files) > 1
+        self.name_width = max(map(len, map(os.path.basename, all_files)))
+        self.name_width = min(self.name_width, 30)
+        if self.multifile:
+            self.of_base = os.path.dirname(kwargs.get('of', '.'))
+
+        for filename in all_files:
+            self.copy_file(filename, **kwargs)
+
+    def copy_file(self, filename, **kwargs):
+        """Copy an individual file."""
+
         try:
-            log.debug('Attempting to stat: %s' % (input_file,))
-            info = os.stat(input_file)
+            log.debug('Attempting to stat: %s' % (filename,))
+            info = os.stat(filename)
         except OSError as exc:
             log.error(str(exc))
             sys.exit(2)
 
-        self.filesize = info.st_size
-        log.debug('Detected filesize: %s' % (self.filesize,))
+        name = os.path.basename(filename)
+        max_size = info.st_size or 1
+        log.debug('Detected filesize: %s' % (max_size,))
+        if self.multifile:
+            kwargs['if'] = filename
+            kwargs['of'] = os.path.join(self.of_base, name)
 
         args = ['%s=%s' % pair for pair in kwargs.items()]
         self.pipe = Popen(['dd'] + args, stdout=PIPE, stderr=PIPE)
         self.get_status()
 
         while self.pipe.poll() is None:
-            self.show_progress()
+            self.show_progress(name, max_size)
 
-        self.show_progress(True)
+        self.show_progress(name, max_size, True)
         sys.stdout.write('\n')
 
+
     def get_status(self):
         call(['kill', '-SIGUSR1', str(self.pipe.pid)], stderr=PIPE)
 
-    def show_progress(self, full=False):
+    def show_progress(self, filename, max_size, full=False):
         r, w, x = select.select([self.pipe.stdout, self.pipe.stderr], [], [], 1)
         for source in r:
             if full:
 
             log.debug('Matched progress line: %s' % (m.groupdict(),))
             copied = int(m.group('bytes'))
-            progress = copied / float(self.filesize) * 100.0
+            progress = copied / float(max_size) * 100.0
             p = min(progress, 100)
 
             # display the progress bar
-            sys.stdout.write('\r[%s] %s%%, %s copied at %s     ' % (
+            sys.stdout.write('\r%s [%s] %s%%, %s copied at %s     ' % (
+                filename.ljust(self.name_width)[:self.name_width],
                 ('#' * int(math.ceil(p / 2))).ljust(50, ' '), int(p),
                 m.group('copied'), m.group('speed')
             ))