bug-coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

cp: progress bar :)


From: Andrea Di Pasquale
Subject: cp: progress bar :)
Date: Fri, 21 Dec 2007 22:03:02 +0100

Hi! I've patched coreutils 5.94/6.9 for add cp's progress bar.

It has:
- Dynamic Progress bar in scale 1:2
- Percentage
- Speed copy (Kib/s)
- Dest/source sizes (KiB/MiB/GiB)
- ETA

Example:
- 1 file copied:

address@hidden:~:$ ./cp -B /mnt/usbdisk/Firefox\ 2.0/Firefox\ Setup\ 
2.0.0.6.exe .
 [====================>                             ]  42% |
896,00 KiB/s |       2,38/5,54 MiB | ETA: 00:00:03


- N files copied (recursive/verbose mode):

address@hidden:~:$ ./cp -rfvB /mnt/usbdisk/Soft/ .
`/mnt/usbdisk/Soft/' -> `./Soft'
`/mnt/usbdisk/Soft/2007' -> `./Soft/2007'
`/mnt/usbdisk/Soft/2007/moca.tar.bz2' -> `./Soft/2007/moca.tar.bz2'
 [==================================================] 100% |
896,00 KiB/s |      17,32/17,32 MiB | ETA: 00:00:00
`/mnt/usbdisk/Soft/2007/tinit.tar.gz' -> `./Soft/2007/tinit.tar.gz'
 [==================================================] 100% |
896,00 KiB/s |      27,36/27,36 MiB | ETA: 00:00:00
`/mnt/usbdisk/Soft/2006' -> `./Soft/2006'
`/mnt/usbdisk/Soft/2006/aapd.tar.gz' -> `./Soft/2006/aapd.tar.gz'
 [==================================================] 100% |
896,00 KiB/s |       2,72/2,72 MiB | ETA: 00:00:00
`/mnt/usbdisk/Soft/2006/six.tar.bz2' -> `./Soft/2006/six.tar.bz2'
 [==================================================] 100% |
612,16 KiB/s |     522,96/522,96 KiB | ETA: 00:00:00


I attach progress bar patch for 5.94 and 6.9 versions.
Here, i can to paste 6.9 patch:

--- copy.c    2007-03-18 22:36:43.000000000 +0100
+++ copy.c    2007-12-21 16:18:17.000000000 +0100
@@ -17,6 +17,8 @@

 /* Extracted from cp.c and librarified by Jim Meyering.  */

+/* Progress bar support add by Andrea Di Pasquale (whyx) email:
address@hidden */
+
 #include <config.h>
 #include <stdio.h>
 #include <assert.h>
@@ -244,6 +246,175 @@
   return lchmod (name, mode);
 }

+/* This function displays a progress bar
+   if the progress flag is set.
+   It uses a 1:2 scales. */
+
+void
+progress_bar_print(size_t dim_tot, size_t dim_cur)
+{
+  int i;
+  size_t per_tot, per_cur, per_tot_scl, per_cur_scl;
+
+  /* Check:
+     if filesize is less than 1 KiB, exit */
+  if (! (dim_tot / 1024))
+    return;
+
+  /* display size in KiB */
+  dim_tot /= 1024;
+  dim_cur /= 1024;
+
+  per_tot = 100;
+  /* total percentage */
+  per_cur = (per_tot * dim_cur) / dim_tot;
+  /* current percentage */
+
+  /* 1:2 scale */
+  per_tot_scl = per_tot / 2;
+  per_cur_scl = per_cur / 2;
+
+  /* Refresh ther bar indicator */
+  printf("\r [");
+
+  /* Display the bar indicator:
+     - =   : indicates a part the bar
+     - >   : indicates the end of the bar
+             (if it's finish, convert '>' to '='*/
+  for (i = 0; i < per_cur_scl; i++)
+    if ((i + 1) == per_cur_scl)
+      if (per_cur_scl == 50)
+        putchar('=');
+      else
+        putchar('>');
+    else
+      putchar('=');
+
+  for (i = per_cur_scl; i < per_tot_scl; i++)
+    putchar(' ');
+
+  printf("] %3d\% | ", per_cur);
+  fflush(stdout);
+}
+
+size_t speed = 0;
+float speed_last = 0;
+
+/* This function displays speed copy
+   if the progress flag is set. */
+
+void
+progress_bar_print_speed(struct tm *tm_init)
+{
+  time_t time_cur;
+  struct tm tm_cur;
+  float speed_, speed_si = (float) 1024;
+
+  time_cur = time(NULL);
+  tm_cur = *(struct tm *) localtime(&time_cur);
+
+  speed_ = (float) speed;
+
+  if (tm_init->tm_sec == tm_cur.tm_sec)
+    {
+      if (tm_init->tm_sec == 60)
+        tm_init->tm_sec = 0;
+      else
+        tm_init->tm_sec += 1;
+
+      speed_last = speed_;
+      speed = 0;
+    }
+  else if (tm_init->tm_sec != tm_cur.tm_sec + 1)
+      /* If the disk crashes, again */
+      tm_init->tm_sec = tm_cur.tm_sec + 1;
+
+  if (speed_last == 0)
+      speed_last = speed_;
+
+  /* bytes in KiB */
+  printf("%12.02f KiB/s | ", speed_last / speed_si,
+         tm_init->tm_hour, tm_init->tm_min, tm_init->tm_sec,
+         tm_cur.tm_hour, tm_cur.tm_min, tm_cur.tm_sec);
+
+
+  fflush(stdout);
+}
+
+/* This function displays size source/dest files copy
+   if the progress flag is set. */
+
+void
+progress_bar_print_size(size_t dim_tot, size_t dim_cur)
+{
+  char dim_type;
+  float dim_tot_, dim_cur_, dim_si = (float) 1024;
+
+  dim_tot_ = (float) dim_tot;
+  dim_cur_ = (float) dim_cur;
+
+  /* display size in KiB */
+  dim_tot_ /= dim_si;
+  dim_cur_ /= dim_si;
+  dim_type = 'k';
+
+  /* If possible, convert in MiB */
+  if (dim_tot / (1024 * 1024))
+    {
+      dim_tot_ /= dim_si;
+      dim_cur_ /= dim_si;
+      dim_type = 'M';
+
+      /* If possible, convert in GiB */
+      if (dim_tot / (1024 * 1024 * 1024))
+        {
+          dim_tot_ /= dim_si;
+          dim_cur_ /= dim_si;
+          dim_type = 'G';
+        }
+    }
+
+  printf("%10.02f/%.02f %s | ", dim_cur_, dim_tot_,
+         dim_type == 'k' ? "KiB" : dim_type == 'M' ? "MiB" : "GiB");
+
+  fflush(stdout);
+}
+
+/* This function displays ETA copy
+   if the progress flag is set. */
+
+void
+progress_bar_print_eta(size_t dim_tot, size_t dim_cur)
+{
+  size_t dim_diff = 0,
+         speed_last_ = (size_t) speed_last,
+         eta = 0;
+  int sec, min, hour;
+
+  /* Convert in KiB */
+  dim_tot /= 1024;
+  dim_cur /= 1024;
+
+  dim_diff = dim_tot - dim_cur;
+  speed_last_ /= 1024;
+
+  /* speed_last_ : 1 sec = dim_diff : eta
+
+     eta = 1 * dim_diff
+           ------------
+           speed_last_  */
+
+  eta = dim_diff / speed_last_;
+
+  min = eta / 60;
+  sec = eta - (min * 60);
+  hour = min / 60;
+
+  printf("ETA: %02d:%02d:%02d", hour, min, sec);
+
+  fflush(stdout);
+}
+
 /* Copy a regular file from SRC_NAME to DST_NAME.
    If the source file contains holes, copies holes and blocks of zeros
    in the source file as holes in the destination file.
@@ -270,6 +441,12 @@
   struct stat sb;
   struct stat src_open_sb;
   bool return_val = true;
+  /* Progress bar */
+  size_t dim_tot = 0,
+         dim_cur = 0;
+  /* speed time */
+  time_t time_init;
+  struct tm tm_init;

   source_desc = open (src_name, O_RDONLY | O_BINARY);
   if (source_desc < 0)
@@ -407,6 +584,13 @@
       buf_alloc = xmalloc (buf_size + buf_alignment_slop);
       buf = ptr_align (buf_alloc, buf_alignment);

+      if (x->progress)
+        {
+          time_init = time(NULL);
+          tm_init = *(struct tm *) localtime(&time_init);
+          tm_init.tm_sec += 1;
+        }
+
       for (;;)
     {
       word *wp = NULL;
@@ -481,6 +665,28 @@
           return_val = false;
           goto close_src_and_dst_desc;
         }
+
+             /* if the progress flag is set, it uses a progress bar */
+             if (x->progress)
+               {
+                    dim_tot = src_sb->st_size;
+                    dim_cur += n;
+
+                    /* print progress bar */
+                    progress_bar_print(dim_tot, dim_cur);
+
+                    speed += n;
+
+                    /* print progress bar speed */
+                    progress_bar_print_speed(&tm_init);
+
+                    /* print progress bar size */
+                    progress_bar_print_size(dim_tot, dim_cur);
+
+                    /* print progress bar ETA */
+                    progress_bar_print_eta(dim_tot, dim_cur);
+               }
+
           last_write_made_hole = false;

           /* A short read on a regular file means EOF.  */
@@ -489,6 +695,9 @@
         }
     }

+        if (x->progress)
+            putchar('\n');
+
       /* If the file ends with a `hole', we need to do something to record
      the length of the file.  On modern systems, calling ftruncate does
      the job.  On systems without native ftruncate support, we have to


--- copy.h    2005-07-03 11:31:19.000000000 +0200
+++ copy.h    2007-12-18 23:32:14.000000000 +0100
@@ -83,6 +83,9 @@
 {
   enum backup_type backup_type;

+  /* If true, Display a progress bar */
+  bool progress;
+
   /* If true, copy all files except (directories and, if not dereferencing
      them, symbolic links,) as if they were regular files.  */
   bool copy_as_regular;


--- cp.c    2005-09-16 09:50:33.000000000 +0200
+++ cp.c    2007-12-18 23:30:47.000000000 +0100
@@ -117,6 +117,7 @@
 {
   {"archive", no_argument, NULL, 'a'},
   {"backup", optional_argument, NULL, 'b'},
+  {"progress", no_argument, NULL, 'B'},
   {"copy-contents", no_argument, NULL, COPY_CONTENTS_OPTION},
   {"dereference", no_argument, NULL, 'L'},
   {"force", no_argument, NULL, 'f'},
@@ -170,6 +171,7 @@
   -a, --archive                same as -dpR\n\
       --backup[=CONTROL]       make a backup of each existing destination
file\n\
   -b                           like --backup but does not accept an
argument\n\
+  -B  --progress               show a progress bar (file > 1 kB)\n\
       --copy-contents          copy contents of special files when
recursive\n\
   -d                           same as --no-dereference --preserve=link\n\
 "), stdout);
@@ -672,6 +674,7 @@
 static void
 cp_option_init (struct cp_options *x)
 {
+  x->progress = false;
   x->copy_as_regular = true;
   x->dereference = DEREF_UNDEFINED;
   x->unlink_dest_before_opening = false;
@@ -811,7 +814,7 @@
      we'll actually use backup_suffix_string.  */
   backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX");

-  while ((c = getopt_long (argc, argv, "abdfHilLprst:uvxPRS:T",
+  while ((c = getopt_long (argc, argv, "abBdfHilLprst:uvxPRS:T",
                long_opts, NULL))
      != -1)
     {
@@ -838,6 +841,10 @@
         version_control_string = optarg;
       break;

+    case 'B':
+      x.progress = true;
+      break;
+
     case COPY_CONTENTS_OPTION:
       copy_contents = true;
       break;


If you want to use it:

$ cd coreutils-version/src
$ patch -p0 < path/version/copy_c.diff
$ patch -p0 < path/version/copy_h.diff
$ patch -p0 < path/version/cp.diff
$ cd..
$ ./configure && make
$ su -
# make install

I'm happy finally :)

For questions and other, address@hidden

Thank you for coreutils :)
Andrea

Attachment: cp-progress_bar-coreutils-5.97.tar.gz
Description: GNU Zip compressed data

Attachment: cp-progress_bar-coreutils-6.9.tar.gz
Description: GNU Zip compressed data


reply via email to

[Prev in Thread] Current Thread [Next in Thread]