[Top][All Lists]
[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
cp-progress_bar-coreutils-5.97.tar.gz
Description: GNU Zip compressed data
cp-progress_bar-coreutils-6.9.tar.gz
Description: GNU Zip compressed data
- cp: progress bar :),
Andrea Di Pasquale <=