Last active
March 20, 2019 05:52
-
-
Save kamawanu/bca612d3d1cd28373b7d1df1214a0ada to your computer and use it in GitHub Desktop.
progress cp/mv https://github.com/atdt/advcpmv http://www.tecmint.com/advanced-copy-command-shows-progress-bar-while-copying-files/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
wget http://ftp.gnu.org/gnu/coreutils/coreutils-8.21.tar.xz | |
tar xvJf coreutils-8.21.tar.xz | |
cd coreutils-8.21/ | |
#wget https://raw.githubusercontent.com/atdt/advcpmv/master/advcpmv-0.5-8.21.patch | |
#wget https://raw.githubusercontent.com/atdt/advcpmv/master/advcpmv-0.5-8.21.patch | |
patch -p1 -i ../advcpmv-0.5-8.21.patch | |
./configure | |
make |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff -crB coreutils-8.21/src/copy.c coreutils-8.21-patch0.5/src/copy.c | |
*** coreutils-8.21/src/copy.c 2013-02-07 10:37:05.000000000 +0100 | |
--- coreutils-8.21-patch0.5/src/copy.c 2013-02-23 12:53:51.000000000 +0100 | |
*************** | |
*** 135,140 **** | |
--- 135,190 ---- | |
return err; | |
} | |
+ /* BEGIN progress mod */ | |
+ static void file_progress_bar ( char * _cDest, int _iBarLength, int _iProgress, int _iTotal ) | |
+ { | |
+ // write number to progress bar | |
+ float fPercent = ( float ) _iProgress / ( float ) _iTotal * 100.f; | |
+ sprintf ( _cDest + ( _iBarLength - 6 ), "%4.1f", fPercent ); | |
+ // remove zero | |
+ _cDest[_iBarLength - 2] = ' '; | |
+ | |
+ // fill rest with '-' | |
+ int i; | |
+ for ( i = 1; i <= _iBarLength - 9; i++ ) | |
+ { | |
+ if ( fPercent > ( float ) ( i - 1 ) / ( _iBarLength - 10 ) * 100.f ) | |
+ _cDest[i] = '|'; | |
+ else | |
+ _cDest[i] = '-'; | |
+ } | |
+ } | |
+ | |
+ int file_size_format ( char * _cDst, int _iSize, int _iCounter ) | |
+ { | |
+ int iCounter = _iCounter; | |
+ double dSize = ( double ) _iSize; | |
+ while ( dSize >= 1000. ) | |
+ { | |
+ dSize /= 1024.; | |
+ iCounter++; | |
+ } | |
+ | |
+ /* get unit */ | |
+ char * sUnit; | |
+ if ( iCounter == 0 ) | |
+ sUnit = "B"; | |
+ else if ( iCounter == 1 ) | |
+ sUnit = "KiB"; | |
+ else if ( iCounter == 2 ) | |
+ sUnit = "MiB"; | |
+ else if ( iCounter == 3 ) | |
+ sUnit = "GiB"; | |
+ else if ( iCounter == 4 ) | |
+ sUnit = "TiB"; | |
+ else | |
+ sUnit = "N/A"; | |
+ | |
+ /* write number */ | |
+ return sprintf ( _cDst, "%5.1f %s", dSize, sUnit ); | |
+ } | |
+ /* END progress mod */ | |
+ | |
/* Copy the regular file open on SRC_FD/SRC_NAME to DST_FD/DST_NAME, | |
honoring the MAKE_HOLES setting and using the BUF_SIZE-byte buffer | |
BUF for temporary storage. Copy no more than MAX_N_READ bytes. | |
*************** | |
*** 151,163 **** | |
bool make_holes, | |
char const *src_name, char const *dst_name, | |
uintmax_t max_n_read, off_t *total_n_read, | |
! bool *last_write_made_hole) | |
{ | |
*last_write_made_hole = false; | |
*total_n_read = 0; | |
while (max_n_read) | |
{ | |
bool make_hole = false; | |
ssize_t n_read = read (src_fd, buf, MIN (max_n_read, buf_size)); | |
--- 201,369 ---- | |
bool make_holes, | |
char const *src_name, char const *dst_name, | |
uintmax_t max_n_read, off_t *total_n_read, | |
! bool *last_write_made_hole | |
! ) | |
{ | |
+ /* BEGIN progress mod */ | |
+ /* create a field of 6 lines */ | |
+ char ** cProgressField = ( char ** ) calloc ( 6, sizeof ( char * ) ); | |
+ /* get console width */ | |
+ int iBarLength = 80; | |
+ struct winsize win; | |
+ if ( ioctl (STDOUT_FILENO, TIOCGWINSZ, (char *) &win) == 0 && win.ws_col > 0 ) | |
+ iBarLength = win.ws_col; | |
+ /* create rows */ | |
+ int it; | |
+ for ( it = 0; it < 6; it++ ) | |
+ { | |
+ cProgressField[it] = ( char * ) malloc ( iBarLength + 1 ); | |
+ /* init with spaces */ | |
+ int j; | |
+ for ( j = 0; j < iBarLength; j++ ) | |
+ cProgressField[it][j] = ' '; | |
+ cProgressField[it][iBarLength] = '\0'; | |
+ } | |
+ | |
+ /* global progress bar? */ | |
+ if ( g_iTotalSize ) | |
+ { | |
+ /* init global progress bar */ | |
+ cProgressField[2][0] = '['; | |
+ cProgressField[2][iBarLength - 8] = ']'; | |
+ cProgressField[2][iBarLength - 7] = ' '; | |
+ cProgressField[2][iBarLength - 1] = '%'; | |
+ | |
+ /* total size */ | |
+ cProgressField[1][iBarLength - 11] = '/'; | |
+ file_size_format ( cProgressField[1] + iBarLength - 9, g_iTotalSize, 1 ); | |
+ | |
+ /* show how many files were written */ | |
+ int sum_length = sprintf ( cProgressField[1], "%d files copied so far...", g_iFilesCopied ); | |
+ cProgressField[1][sum_length] = ' '; | |
+ } | |
+ | |
+ /* truncate filename? */ | |
+ int fn_length; | |
+ if ( strlen ( src_name ) > iBarLength - 22 ) | |
+ fn_length = | |
+ sprintf ( cProgressField[4], "...%s", src_name + ( strlen ( src_name ) - iBarLength + 25 ) ); | |
+ else | |
+ fn_length = sprintf ( cProgressField[4], "%s", src_name ); | |
+ cProgressField[4][fn_length] = ' '; | |
+ | |
+ /* filesize */ | |
+ int file_size = max_n_read; | |
+ struct stat file_stat; | |
+ if (fstat(src_fd, & file_stat) == 0) | |
+ file_size = file_stat.st_size; | |
+ cProgressField[4][iBarLength - 11] = '/'; | |
+ file_size_format ( cProgressField[4] + iBarLength - 9, file_size, 0 ); | |
+ | |
+ int iCountDown = 1; | |
+ char * sProgressBar = cProgressField[5]; | |
+ sProgressBar[0] = '['; | |
+ sProgressBar[iBarLength - 8] = ']'; | |
+ sProgressBar[iBarLength - 7] = ' '; | |
+ sProgressBar[iBarLength - 1] = '%'; | |
+ | |
+ /* this will always save the time in between */ | |
+ struct timeval last_time; | |
+ gettimeofday ( & last_time, NULL ); | |
+ int last_size = g_iTotalWritten; | |
+ /* END progress mod */ | |
+ | |
*last_write_made_hole = false; | |
*total_n_read = 0; | |
while (max_n_read) | |
{ | |
+ /* BEGIN progress mod */ | |
+ if (progress) { | |
+ /* update countdown */ | |
+ iCountDown--; | |
+ if ( iCountDown < 0 ) | |
+ { | |
+ /* average copy speed is assumed to be around 10 MiB/s, just to be safe. | |
+ * the status should be updated about 10 times per second, or approximately | |
+ * once per 1 MiB transferred. */ | |
+ iCountDown = 1024 * 1024 / buf_size; | |
+ /* must be greater than 0 */ | |
+ if (iCountDown < 1) | |
+ iCountDown = 1; | |
+ /* limit */ | |
+ if (iCountDown > 100) | |
+ iCountDown = 100; | |
+ } | |
+ | |
+ /* just print one line with the percentage, but not always */ | |
+ if ( iCountDown == 0 ) | |
+ { | |
+ /* calculate current speed */ | |
+ struct timeval cur_time; | |
+ gettimeofday ( & cur_time, NULL ); | |
+ int cur_size = g_iTotalWritten + *total_n_read / 1024; | |
+ int usec_elapsed = cur_time.tv_usec - last_time.tv_usec; | |
+ double sec_elapsed = ( double ) usec_elapsed / 1000000.f; | |
+ sec_elapsed += ( double ) ( cur_time.tv_sec - last_time.tv_sec ); | |
+ int copy_speed = ( int ) ( ( double ) ( cur_size - last_size ) | |
+ / sec_elapsed ); | |
+ if (copy_speed < 0) | |
+ copy_speed = 0; | |
+ char s_copy_speed[20]; | |
+ file_size_format ( s_copy_speed, copy_speed, 1 ); | |
+ /* update vars */ | |
+ last_time = cur_time; | |
+ last_size = cur_size; | |
+ | |
+ /* how much time has passed since the start? */ | |
+ int isec_elapsed = cur_time.tv_sec - g_oStartTime.tv_sec; | |
+ int sec_remaining = ( int ) ( ( double ) isec_elapsed / cur_size | |
+ * g_iTotalSize ) - isec_elapsed; | |
+ int min_remaining = sec_remaining / 60; | |
+ sec_remaining -= min_remaining * 60; | |
+ int hours_remaining = min_remaining / 60; | |
+ min_remaining -= hours_remaining * 60; | |
+ /* print out */ | |
+ sprintf ( cProgressField[3], | |
+ "Copying at %s/s (about %dh %dm %ds remaining)", s_copy_speed, | |
+ hours_remaining, min_remaining, sec_remaining ); | |
+ | |
+ int fs_len; | |
+ if ( g_iTotalSize ) | |
+ { | |
+ /* global progress bar */ | |
+ file_progress_bar ( cProgressField[2], iBarLength, | |
+ g_iTotalWritten + *total_n_read / 1024, g_iTotalSize ); | |
+ | |
+ /* print the global status */ | |
+ fs_len = file_size_format ( cProgressField[1] + iBarLength - 21, | |
+ g_iTotalWritten + *total_n_read / 1024, 1 ); | |
+ cProgressField[1][iBarLength - 21 + fs_len] = ' '; | |
+ } | |
+ | |
+ /* current progress bar */ | |
+ file_progress_bar ( sProgressBar, iBarLength, *total_n_read, file_size ); | |
+ | |
+ /* print the status */ | |
+ fs_len = file_size_format ( cProgressField[4] + iBarLength - 21, *total_n_read, 0 ); | |
+ cProgressField[4][iBarLength - 21 + fs_len] = ' '; | |
+ | |
+ /* print the field */ | |
+ for ( it = g_iTotalSize ? 0 : 3; it < 6; it++ ) | |
+ { | |
+ printf ( "\033[K%s\n", cProgressField[it] ); | |
+ if ( strlen ( cProgressField[it] ) < iBarLength ) | |
+ printf ( "" ); | |
+ } | |
+ if ( g_iTotalSize ) | |
+ printf ( "\r\033[6A" ); | |
+ else | |
+ printf ( "\r\033[3A" ); | |
+ fflush ( stdout ); | |
+ } | |
+ } | |
+ /* END progress mod */ | |
+ | |
bool make_hole = false; | |
ssize_t n_read = read (src_fd, buf, MIN (max_n_read, buf_size)); | |
*************** | |
*** 215,220 **** | |
--- 421,439 ---- | |
*last_write_made_hole = make_hole; | |
} | |
+ | |
+ if (progress) { | |
+ /* BEGIN progress mod */ | |
+ /* update total size */ | |
+ g_iTotalWritten += *total_n_read / 1024; | |
+ g_iFilesCopied++; | |
+ | |
+ int i; | |
+ for ( i = 0; i < 6; i++ ) | |
+ free ( cProgressField[i] ); | |
+ free ( cProgressField ); | |
+ /* END progress mod */ | |
+ } | |
return true; | |
} | |
diff -crB coreutils-8.21/src/copy.h coreutils-8.21-patch0.5/src/copy.h | |
*** coreutils-8.21/src/copy.h 2013-01-31 01:46:24.000000000 +0100 | |
--- coreutils-8.21-patch0.5/src/copy.h 2013-02-23 12:53:51.000000000 +0100 | |
*************** | |
*** 227,232 **** | |
--- 227,235 ---- | |
/* If true, create symbolic links instead of copying files. | |
Create destination directories as usual. */ | |
bool symbolic_link; | |
+ | |
+ /* If true, draw a nice progress bar on screen */ | |
+ bool progress_bar; | |
/* If true, do not copy a nondirectory that has an existing destination | |
with the same or newer modification time. */ | |
*************** | |
*** 286,289 **** | |
--- 289,303 ---- | |
bool chown_failure_ok (struct cp_options const *) _GL_ATTRIBUTE_PURE; | |
mode_t cached_umask (void); | |
+ /* BEGIN progress mod */ | |
+ int file_size_format ( char * _cDst, int _iSize, int _iCounter ); | |
+ | |
+ long g_iTotalSize; | |
+ long g_iTotalWritten; | |
+ int g_iFilesCopied; | |
+ struct timeval g_oStartTime; | |
+ int g_iTotalFiles; | |
+ bool progress; | |
+ /* END progress mod */ | |
+ | |
#endif | |
diff -crB coreutils-8.21/src/cp.c coreutils-8.21-patch0.5/src/cp.c | |
*** coreutils-8.21/src/cp.c 2013-02-07 10:37:05.000000000 +0100 | |
--- coreutils-8.21-patch0.5/src/cp.c 2013-02-23 12:53:51.000000000 +0100 | |
*************** | |
*** 141,146 **** | |
--- 141,147 ---- | |
{"target-directory", required_argument, NULL, 't'}, | |
{"update", no_argument, NULL, 'u'}, | |
{"verbose", no_argument, NULL, 'v'}, | |
+ {"progress-bar", no_argument, NULL, 'g'}, | |
{GETOPT_HELP_OPTION_DECL}, | |
{GETOPT_VERSION_OPTION_DECL}, | |
{NULL, 0, NULL, 0} | |
*************** | |
*** 178,183 **** | |
--- 179,185 ---- | |
-f, --force if an existing destination file cannot be\n\ | |
opened, remove it and try again (this option\n\ | |
is ignored when the -n option is also used)\n\ | |
+ -g, --progress-bar add progress-bar\n\ | |
-i, --interactive prompt before overwrite (overrides a previous -n\ | |
\n\ | |
option)\n\ | |
*************** | |
*** 617,622 **** | |
--- 619,675 ---- | |
error (EXIT_FAILURE, 0, _("target %s is not a directory"), | |
quote (file[n_files - 1])); | |
} | |
+ | |
+ /* BEGIN progress mod */ | |
+ struct timeval start_time; | |
+ if (progress) { | |
+ g_iTotalSize = 0; | |
+ g_iFilesCopied = 0; | |
+ g_iTotalWritten = 0; | |
+ | |
+ /* save time */ | |
+ gettimeofday ( & start_time, NULL ); | |
+ g_oStartTime = start_time; | |
+ | |
+ printf ( "Calculating total size... \r" ); | |
+ fflush ( stdout ); | |
+ long iTotalSize = 0; | |
+ int iFiles = n_files; | |
+ if ( ! target_directory ) | |
+ iFiles = n_files - 1; | |
+ int j; | |
+ for (j = 0; j < iFiles; j++) | |
+ { | |
+ /* call du -s for each file */ | |
+ /* create command */ | |
+ char command[1024]; | |
+ sprintf ( command, "du -s \"%s\"", file[j] ); | |
+ /* TODO: replace all quote signs in file[i] */ | |
+ | |
+ FILE *fp; | |
+ char output[1024]; | |
+ | |
+ /* run command */ | |
+ fp = popen(command, "r"); | |
+ if (fp == NULL || fgets(output, sizeof(output)-1, fp) == NULL) { | |
+ printf("failed to run du.\n" ); | |
+ } | |
+ else | |
+ { | |
+ /* isolate size */ | |
+ strchr ( output, '\t' )[0] = '\0'; | |
+ iTotalSize += atol ( output ); | |
+ | |
+ printf ( "Calculating total size... %ld\r", iTotalSize ); | |
+ fflush ( stdout ); | |
+ } | |
+ | |
+ /* close */ | |
+ pclose(fp); | |
+ } | |
+ g_iTotalSize = iTotalSize; | |
+ } | |
+ /* END progress mod */ | |
if (target_directory) | |
{ | |
*************** | |
*** 759,764 **** | |
--- 812,857 ---- | |
ok = copy (source, new_dest, 0, x, &unused, NULL); | |
} | |
+ | |
+ /* BEGIN progress mod */ | |
+ if (progress) { | |
+ /* remove everything */ | |
+ int i; | |
+ if ( g_iTotalSize ) | |
+ { | |
+ for ( i = 0; i < 6; i++ ) | |
+ printf ( "\033[K\n" ); | |
+ printf ( "\r\033[6A" ); | |
+ } | |
+ else | |
+ { | |
+ for ( i = 0; i < 3; i++ ) | |
+ printf ( "\033[K\n" ); | |
+ printf ( "\r\033[3A" ); | |
+ } | |
+ | |
+ /* save time */ | |
+ struct timeval end_time; | |
+ gettimeofday ( & end_time, NULL ); | |
+ int usec_elapsed = end_time.tv_usec - start_time.tv_usec; | |
+ double sec_elapsed = ( double ) usec_elapsed / 1000000.f; | |
+ sec_elapsed += ( double ) ( end_time.tv_sec - start_time.tv_sec ); | |
+ | |
+ /* get total size */ | |
+ char sTotalWritten[20]; | |
+ file_size_format ( sTotalWritten, g_iTotalSize, 1 ); | |
+ /* TODO: using g_iTotalWritten would be more correct, but is less accurate */ | |
+ | |
+ /* calculate speed */ | |
+ int copy_speed = ( int ) ( ( double ) g_iTotalWritten / sec_elapsed ); | |
+ char s_copy_speed[20]; | |
+ file_size_format ( s_copy_speed, copy_speed, 1 ); | |
+ | |
+ /* good-bye message */ | |
+ printf ( "%d files (%s) copied in %.1f seconds (%s/s).\n", g_iFilesCopied, sTotalWritten, | |
+ sec_elapsed, s_copy_speed ); | |
+ } | |
+ /* END progress mod */ | |
return ok; | |
} | |
*************** | |
*** 793,798 **** | |
--- 886,892 ---- | |
x->recursive = false; | |
x->sparse_mode = SPARSE_AUTO; | |
x->symbolic_link = false; | |
+ x->progress_bar = false; | |
x->set_mode = false; | |
x->mode = 0; | |
*************** | |
*** 933,939 **** | |
we'll actually use backup_suffix_string. */ | |
backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX"); | |
! while ((c = getopt_long (argc, argv, "abdfHilLnprst:uvxPRS:T", | |
long_opts, NULL)) | |
!= -1) | |
{ | |
--- 1027,1033 ---- | |
we'll actually use backup_suffix_string. */ | |
backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX"); | |
! while ((c = getopt_long (argc, argv, "abdfgHilLnprst:uvxPRS:T", | |
long_opts, NULL)) | |
!= -1) | |
{ | |
*************** | |
*** 990,995 **** | |
--- 1084,1093 ---- | |
x.unlink_dest_after_failed_open = true; | |
break; | |
+ case 'g': | |
+ progress = true; | |
+ break; | |
+ | |
case 'H': | |
x.dereference = DEREF_COMMAND_LINE_ARGUMENTS; | |
break; | |
diff -crB coreutils-8.21/src/mv.c coreutils-8.21-patch0.5/src/mv.c | |
*** coreutils-8.21/src/mv.c 2013-02-07 10:37:05.000000000 +0100 | |
--- coreutils-8.21-patch0.5/src/mv.c 2013-03-12 21:23:58.000000000 +0100 | |
*************** | |
*** 64,69 **** | |
--- 64,70 ---- | |
{"target-directory", required_argument, NULL, 't'}, | |
{"update", no_argument, NULL, 'u'}, | |
{"verbose", no_argument, NULL, 'v'}, | |
+ {"progress-bar", no_argument, NULL, 'g'}, | |
{GETOPT_HELP_OPTION_DECL}, | |
{GETOPT_VERSION_OPTION_DECL}, | |
{NULL, 0, NULL, 0} | |
*************** | |
*** 165,171 **** | |
bool copy_into_self; | |
bool rename_succeeded; | |
bool ok = copy (source, dest, false, x, ©_into_self, &rename_succeeded); | |
! | |
if (ok) | |
{ | |
char const *dir_to_remove; | |
--- 166,172 ---- | |
bool copy_into_self; | |
bool rename_succeeded; | |
bool ok = copy (source, dest, false, x, ©_into_self, &rename_succeeded); | |
! | |
if (ok) | |
{ | |
char const *dir_to_remove; | |
*************** | |
*** 300,305 **** | |
--- 301,307 ---- | |
\n\ | |
-b like --backup but does not accept an argument\n\ | |
-f, --force do not prompt before overwriting\n\ | |
+ -g, --progress-bar add progress-bar\n\ | |
-i, --interactive prompt before overwrite\n\ | |
-n, --no-clobber do not overwrite an existing file\n\ | |
If you specify more than one of -i, -f, -n, only the final one takes effect.\n\ | |
*************** | |
*** 368,374 **** | |
we'll actually use backup_suffix_string. */ | |
backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX"); | |
! while ((c = getopt_long (argc, argv, "bfint:uvS:T", long_options, NULL)) | |
!= -1) | |
{ | |
switch (c) | |
--- 370,376 ---- | |
we'll actually use backup_suffix_string. */ | |
backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX"); | |
! while ((c = getopt_long (argc, argv, "bfint:uvgS:T", long_options, NULL)) | |
!= -1) | |
{ | |
switch (c) | |
*************** | |
*** 414,419 **** | |
--- 416,424 ---- | |
case 'v': | |
x.verbose = true; | |
break; | |
+ case 'g': | |
+ progress = true; | |
+ break; | |
case 'S': | |
make_backups = true; | |
backup_suffix_string = optarg; | |
*************** | |
*** 476,481 **** | |
--- 481,537 ---- | |
: no_backups); | |
hash_init (); | |
+ | |
+ /* BEGIN progress mod */ | |
+ struct timeval start_time; | |
+ | |
+ if(progress) { | |
+ g_iTotalSize = 0; | |
+ g_iFilesCopied = 0; | |
+ g_iTotalWritten = 0; | |
+ | |
+ gettimeofday (& start_time, NULL); | |
+ g_oStartTime = start_time; | |
+ | |
+ printf ("Calculating total size... \r"); | |
+ fflush (stdout); | |
+ long iTotalSize = 0; | |
+ int iFiles = n_files; | |
+ if ( !target_directory ) | |
+ iFiles = 1; | |
+ int j; | |
+ for (j = 0; j < iFiles; j++) | |
+ { | |
+ /* call du -s for each file */ | |
+ /* create command */ | |
+ char command[1024]; | |
+ sprintf ( command, "du -s \"%s\"", file[j] ); | |
+ /* TODO: replace all quote signs in file[i] */ | |
+ | |
+ FILE *fp; | |
+ char output[1024]; | |
+ | |
+ /* run command */ | |
+ fp = popen(command, "r"); | |
+ if (fp == NULL || fgets(output, sizeof(output)-1, fp) == NULL) { | |
+ printf("failed to run du.\n" ); | |
+ } | |
+ else | |
+ { | |
+ /* isolate size */ | |
+ strchr ( output, '\t' )[0] = '\0'; | |
+ iTotalSize += atol ( output ); | |
+ | |
+ printf ( "Calculating total size... %ld\r", iTotalSize ); | |
+ fflush ( stdout ); | |
+ } | |
+ | |
+ /* close */ | |
+ pclose(fp); | |
+ } | |
+ g_iTotalSize = iTotalSize; | |
+ } | |
+ /* END progress mod */ | |
if (target_directory) | |
{ | |
*************** | |
*** 493,498 **** | |
--- 549,594 ---- | |
} | |
else | |
ok = movefile (file[0], file[1], false, &x); | |
+ | |
+ /* BEGIN progress mod */ | |
+ if (progress) { | |
+ /* remove everything */ | |
+ int i; | |
+ if ( g_iTotalSize ) | |
+ { | |
+ for ( i = 0; i < 6; i++ ) | |
+ printf ( "\033[K\n" ); | |
+ printf ( "\r\033[6A" ); | |
+ } | |
+ else | |
+ { | |
+ for ( i = 0; i < 3; i++ ) | |
+ printf ( "\033[K\n" ); | |
+ printf ( "\r\033[3A" ); | |
+ } | |
+ | |
+ /* save time */ | |
+ struct timeval end_time; | |
+ gettimeofday ( & end_time, NULL ); | |
+ int usec_elapsed = end_time.tv_usec - start_time.tv_usec; | |
+ double sec_elapsed = ( double ) usec_elapsed / 1000000.f; | |
+ sec_elapsed += ( double ) ( end_time.tv_sec - start_time.tv_sec ); | |
+ | |
+ /* get total size */ | |
+ char sTotalWritten[20]; | |
+ file_size_format ( sTotalWritten, g_iTotalSize, 1 ); | |
+ /* TODO: using g_iTotalWritten would be more correct, but is less accurate */ | |
+ | |
+ /* calculate speed */ | |
+ int copy_speed = ( int ) ( ( double ) g_iTotalWritten / sec_elapsed ); | |
+ char s_copy_speed[20]; | |
+ file_size_format ( s_copy_speed, copy_speed, 1 ); | |
+ | |
+ /* good-bye message */ | |
+ printf ( "%d files (%s) moved in %.1f seconds (%s/s).\n", g_iFilesCopied, sTotalWritten, | |
+ sec_elapsed, s_copy_speed ); | |
+ } | |
+ /* END progress mod */ | |
exit (ok ? EXIT_SUCCESS : EXIT_FAILURE); | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Only in coreutils-8.24-patch0.6: advcpmv-0.5-8.21.patch | |
diff -crB coreutils-8.24/src/copy.c coreutils-8.24-patch0.6/src/copy.c | |
*** coreutils-8.24/src/copy.c 2015-06-26 10:05:22.000000000 -0700 | |
--- coreutils-8.24-patch0.6/src/copy.c 2015-08-16 23:54:17.000000000 -0700 | |
*************** | |
*** 196,201 **** | |
--- 196,251 ---- | |
} | |
+ /* BEGIN progress mod */ | |
+ static void file_progress_bar ( char * _cDest, int _iBarLength, int _iProgress, int _iTotal ) | |
+ { | |
+ // write number to progress bar | |
+ float fPercent = ( float ) _iProgress / ( float ) _iTotal * 100.f; | |
+ sprintf ( _cDest + ( _iBarLength - 6 ), "%4.1f", fPercent ); | |
+ // remove zero | |
+ _cDest[_iBarLength - 2] = ' '; | |
+ | |
+ // fill rest with '-' | |
+ int i; | |
+ for ( i = 1; i <= _iBarLength - 9; i++ ) | |
+ { | |
+ if ( fPercent > ( float ) ( i - 1 ) / ( _iBarLength - 10 ) * 100.f ) | |
+ _cDest[i] = '|'; | |
+ else | |
+ _cDest[i] = '-'; | |
+ } | |
+ } | |
+ | |
+ int file_size_format ( char * _cDst, int _iSize, int _iCounter ) | |
+ { | |
+ int iCounter = _iCounter; | |
+ double dSize = ( double ) _iSize; | |
+ while ( dSize >= 1000. ) | |
+ { | |
+ dSize /= 1024.; | |
+ iCounter++; | |
+ } | |
+ | |
+ /* get unit */ | |
+ char * sUnit; | |
+ if ( iCounter == 0 ) | |
+ sUnit = "B"; | |
+ else if ( iCounter == 1 ) | |
+ sUnit = "KiB"; | |
+ else if ( iCounter == 2 ) | |
+ sUnit = "MiB"; | |
+ else if ( iCounter == 3 ) | |
+ sUnit = "GiB"; | |
+ else if ( iCounter == 4 ) | |
+ sUnit = "TiB"; | |
+ else | |
+ sUnit = "N/A"; | |
+ | |
+ /* write number */ | |
+ return sprintf ( _cDst, "%5.1f %s", dSize, sUnit ); | |
+ } | |
+ /* END progress mod */ | |
+ | |
/* Copy the regular file open on SRC_FD/SRC_NAME to DST_FD/DST_NAME, | |
honoring the MAKE_HOLES setting and using the BUF_SIZE-byte buffer | |
BUF for temporary storage. Copy no more than MAX_N_READ bytes. | |
*************** | |
*** 315,320 **** | |
--- 365,383 ---- | |
for each file. Unfortunately that doesn't work for | |
certain files in /proc or /sys with linux kernels. */ | |
} | |
+ | |
+ if (progress) { | |
+ /* BEGIN progress mod */ | |
+ /* update total size */ | |
+ g_iTotalWritten += *total_n_read / 1024; | |
+ g_iFilesCopied++; | |
+ | |
+ int i; | |
+ for ( i = 0; i < 6; i++ ) | |
+ free ( cProgressField[i] ); | |
+ free ( cProgressField ); | |
+ /* END progress mod */ | |
+ } | |
/* Ensure a trailing hole is created, so that subsequent | |
calls of sparse_copy() start at the correct offset. */ | |
diff -crB coreutils-8.24/src/copy.h coreutils-8.24-patch0.6/src/copy.h | |
*** coreutils-8.24/src/copy.h 2015-06-26 10:04:19.000000000 -0700 | |
--- coreutils-8.24-patch0.6/src/copy.h 2015-08-16 23:54:17.000000000 -0700 | |
*************** | |
*** 230,235 **** | |
--- 230,238 ---- | |
/* If true, create symbolic links instead of copying files. | |
Create destination directories as usual. */ | |
bool symbolic_link; | |
+ | |
+ /* If true, draw a nice progress bar on screen */ | |
+ bool progress_bar; | |
/* If true, do not copy a nondirectory that has an existing destination | |
with the same or newer modification time. */ | |
*************** | |
*** 289,292 **** | |
--- 292,306 ---- | |
bool chown_failure_ok (struct cp_options const *) _GL_ATTRIBUTE_PURE; | |
mode_t cached_umask (void); | |
+ /* BEGIN progress mod */ | |
+ int file_size_format ( char * _cDst, int _iSize, int _iCounter ); | |
+ | |
+ long g_iTotalSize; | |
+ long g_iTotalWritten; | |
+ int g_iFilesCopied; | |
+ struct timeval g_oStartTime; | |
+ int g_iTotalFiles; | |
+ bool progress; | |
+ /* END progress mod */ | |
+ | |
#endif | |
diff -crB coreutils-8.24/src/cp.c coreutils-8.24-patch0.6/src/cp.c | |
*** coreutils-8.24/src/cp.c 2015-06-26 10:04:19.000000000 -0700 | |
--- coreutils-8.24-patch0.6/src/cp.c 2015-08-16 23:56:08.000000000 -0700 | |
*************** | |
*** 141,146 **** | |
--- 141,147 ---- | |
{"target-directory", required_argument, NULL, 't'}, | |
{"update", no_argument, NULL, 'u'}, | |
{"verbose", no_argument, NULL, 'v'}, | |
+ {"progress-bar", no_argument, NULL, 'g'}, | |
{GETOPT_SELINUX_CONTEXT_OPTION_DECL}, | |
{GETOPT_HELP_OPTION_DECL}, | |
{GETOPT_VERSION_OPTION_DECL}, | |
*************** | |
*** 179,184 **** | |
--- 180,186 ---- | |
-f, --force if an existing destination file cannot be\n\ | |
opened, remove it and try again (this option\n\ | |
is ignored when the -n option is also used)\n\ | |
+ -g, --progress-bar add progress-bar\n\ | |
-i, --interactive prompt before overwrite (overrides a previous -n\ | |
\n\ | |
option)\n\ | |
*************** | |
*** 624,629 **** | |
--- 626,682 ---- | |
error (EXIT_FAILURE, 0, _("target %s is not a directory"), | |
quote (file[n_files - 1])); | |
} | |
+ | |
+ /* BEGIN progress mod */ | |
+ struct timeval start_time; | |
+ if (progress) { | |
+ g_iTotalSize = 0; | |
+ g_iFilesCopied = 0; | |
+ g_iTotalWritten = 0; | |
+ | |
+ /* save time */ | |
+ gettimeofday ( & start_time, NULL ); | |
+ g_oStartTime = start_time; | |
+ | |
+ printf ( "Calculating total size... \r" ); | |
+ fflush ( stdout ); | |
+ long iTotalSize = 0; | |
+ int iFiles = n_files; | |
+ if ( ! target_directory ) | |
+ iFiles = n_files - 1; | |
+ int j; | |
+ for (j = 0; j < iFiles; j++) | |
+ { | |
+ /* call du -s for each file */ | |
+ /* create command */ | |
+ char command[1024]; | |
+ sprintf ( command, "du -s \"%s\"", file[j] ); | |
+ /* TODO: replace all quote signs in file[i] */ | |
+ | |
+ FILE *fp; | |
+ char output[1024]; | |
+ | |
+ /* run command */ | |
+ fp = popen(command, "r"); | |
+ if (fp == NULL || fgets(output, sizeof(output)-1, fp) == NULL) { | |
+ printf("failed to run du.\n" ); | |
+ } | |
+ else | |
+ { | |
+ /* isolate size */ | |
+ strchr ( output, '\t' )[0] = '\0'; | |
+ iTotalSize += atol ( output ); | |
+ | |
+ printf ( "Calculating total size... %ld\r", iTotalSize ); | |
+ fflush ( stdout ); | |
+ } | |
+ | |
+ /* close */ | |
+ pclose(fp); | |
+ } | |
+ g_iTotalSize = iTotalSize; | |
+ } | |
+ /* END progress mod */ | |
if (target_directory) | |
{ | |
*************** | |
*** 766,771 **** | |
--- 819,864 ---- | |
ok = copy (source, new_dest, 0, x, &unused, NULL); | |
} | |
+ | |
+ /* BEGIN progress mod */ | |
+ if (progress) { | |
+ /* remove everything */ | |
+ int i; | |
+ if ( g_iTotalSize ) | |
+ { | |
+ for ( i = 0; i < 6; i++ ) | |
+ printf ( "\033[K\n" ); | |
+ printf ( "\r\033[6A" ); | |
+ } | |
+ else | |
+ { | |
+ for ( i = 0; i < 3; i++ ) | |
+ printf ( "\033[K\n" ); | |
+ printf ( "\r\033[3A" ); | |
+ } | |
+ | |
+ /* save time */ | |
+ struct timeval end_time; | |
+ gettimeofday ( & end_time, NULL ); | |
+ int usec_elapsed = end_time.tv_usec - start_time.tv_usec; | |
+ double sec_elapsed = ( double ) usec_elapsed / 1000000.f; | |
+ sec_elapsed += ( double ) ( end_time.tv_sec - start_time.tv_sec ); | |
+ | |
+ /* get total size */ | |
+ char sTotalWritten[20]; | |
+ file_size_format ( sTotalWritten, g_iTotalSize, 1 ); | |
+ /* TODO: using g_iTotalWritten would be more correct, but is less accurate */ | |
+ | |
+ /* calculate speed */ | |
+ int copy_speed = ( int ) ( ( double ) g_iTotalWritten / sec_elapsed ); | |
+ char s_copy_speed[20]; | |
+ file_size_format ( s_copy_speed, copy_speed, 1 ); | |
+ | |
+ /* good-bye message */ | |
+ printf ( "%d files (%s) copied in %.1f seconds (%s/s).\n", g_iFilesCopied, sTotalWritten, | |
+ sec_elapsed, s_copy_speed ); | |
+ } | |
+ /* END progress mod */ | |
return ok; | |
} | |
*************** | |
*** 801,806 **** | |
--- 894,900 ---- | |
x->recursive = false; | |
x->sparse_mode = SPARSE_AUTO; | |
x->symbolic_link = false; | |
+ x->progress_bar = false; | |
x->set_mode = false; | |
x->mode = 0; | |
*************** | |
*** 943,949 **** | |
we'll actually use backup_suffix_string. */ | |
backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX"); | |
! while ((c = getopt_long (argc, argv, "abdfHilLnprst:uvxPRS:TZ", | |
long_opts, NULL)) | |
!= -1) | |
{ | |
--- 1037,1043 ---- | |
we'll actually use backup_suffix_string. */ | |
backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX"); | |
! while ((c = getopt_long (argc, argv, "abdfgHilLnprst:uvxPRS:TZ", | |
long_opts, NULL)) | |
!= -1) | |
{ | |
*************** | |
*** 1000,1005 **** | |
--- 1094,1103 ---- | |
x.unlink_dest_after_failed_open = true; | |
break; | |
+ case 'g': | |
+ progress = true; | |
+ break; | |
+ | |
case 'H': | |
x.dereference = DEREF_COMMAND_LINE_ARGUMENTS; | |
break; | |
diff -crB coreutils-8.24/src/mv.c coreutils-8.24-patch0.6/src/mv.c | |
*** coreutils-8.24/src/mv.c 2015-06-26 10:04:19.000000000 -0700 | |
--- coreutils-8.24-patch0.6/src/mv.c 2015-08-16 23:56:44.000000000 -0700 | |
*************** | |
*** 65,70 **** | |
--- 65,71 ---- | |
{"target-directory", required_argument, NULL, 't'}, | |
{"update", no_argument, NULL, 'u'}, | |
{"verbose", no_argument, NULL, 'v'}, | |
+ {"progress-bar", no_argument, NULL, 'g'}, | |
{GETOPT_HELP_OPTION_DECL}, | |
{GETOPT_VERSION_OPTION_DECL}, | |
{NULL, 0, NULL, 0} | |
*************** | |
*** 167,173 **** | |
bool copy_into_self; | |
bool rename_succeeded; | |
bool ok = copy (source, dest, false, x, ©_into_self, &rename_succeeded); | |
! | |
if (ok) | |
{ | |
char const *dir_to_remove; | |
--- 168,174 ---- | |
bool copy_into_self; | |
bool rename_succeeded; | |
bool ok = copy (source, dest, false, x, ©_into_self, &rename_succeeded); | |
! | |
if (ok) | |
{ | |
char const *dir_to_remove; | |
*************** | |
*** 302,307 **** | |
--- 303,309 ---- | |
\n\ | |
-b like --backup but does not accept an argument\n\ | |
-f, --force do not prompt before overwriting\n\ | |
+ -g, --progress-bar add progress-bar\n\ | |
-i, --interactive prompt before overwrite\n\ | |
-n, --no-clobber do not overwrite an existing file\n\ | |
If you specify more than one of -i, -f, -n, only the final one takes effect.\n\ | |
*************** | |
*** 373,379 **** | |
we'll actually use backup_suffix_string. */ | |
backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX"); | |
! while ((c = getopt_long (argc, argv, "bfint:uvS:TZ", long_options, NULL)) | |
!= -1) | |
{ | |
switch (c) | |
--- 375,381 ---- | |
we'll actually use backup_suffix_string. */ | |
backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX"); | |
! while ((c = getopt_long (argc, argv, "bfint:uvgS:TZ", long_options, NULL)) | |
!= -1) | |
{ | |
switch (c) | |
*************** | |
*** 419,424 **** | |
--- 421,429 ---- | |
case 'v': | |
x.verbose = true; | |
break; | |
+ case 'g': | |
+ progress = true; | |
+ break; | |
case 'S': | |
make_backups = true; | |
backup_suffix_string = optarg; | |
*************** | |
*** 490,495 **** | |
--- 495,551 ---- | |
: no_backups); | |
hash_init (); | |
+ | |
+ /* BEGIN progress mod */ | |
+ struct timeval start_time; | |
+ | |
+ if(progress) { | |
+ g_iTotalSize = 0; | |
+ g_iFilesCopied = 0; | |
+ g_iTotalWritten = 0; | |
+ | |
+ gettimeofday (& start_time, NULL); | |
+ g_oStartTime = start_time; | |
+ | |
+ printf ("Calculating total size... \r"); | |
+ fflush (stdout); | |
+ long iTotalSize = 0; | |
+ int iFiles = n_files; | |
+ if ( !target_directory ) | |
+ iFiles = 1; | |
+ int j; | |
+ for (j = 0; j < iFiles; j++) | |
+ { | |
+ /* call du -s for each file */ | |
+ /* create command */ | |
+ char command[1024]; | |
+ sprintf ( command, "du -s \"%s\"", file[j] ); | |
+ /* TODO: replace all quote signs in file[i] */ | |
+ | |
+ FILE *fp; | |
+ char output[1024]; | |
+ | |
+ /* run command */ | |
+ fp = popen(command, "r"); | |
+ if (fp == NULL || fgets(output, sizeof(output)-1, fp) == NULL) { | |
+ printf("failed to run du.\n" ); | |
+ } | |
+ else | |
+ { | |
+ /* isolate size */ | |
+ strchr ( output, '\t' )[0] = '\0'; | |
+ iTotalSize += atol ( output ); | |
+ | |
+ printf ( "Calculating total size... %ld\r", iTotalSize ); | |
+ fflush ( stdout ); | |
+ } | |
+ | |
+ /* close */ | |
+ pclose(fp); | |
+ } | |
+ g_iTotalSize = iTotalSize; | |
+ } | |
+ /* END progress mod */ | |
if (target_directory) | |
{ | |
*************** | |
*** 507,512 **** | |
--- 563,608 ---- | |
} | |
else | |
ok = movefile (file[0], file[1], false, &x); | |
+ | |
+ /* BEGIN progress mod */ | |
+ if (progress) { | |
+ /* remove everything */ | |
+ int i; | |
+ if ( g_iTotalSize ) | |
+ { | |
+ for ( i = 0; i < 6; i++ ) | |
+ printf ( "\033[K\n" ); | |
+ printf ( "\r\033[6A" ); | |
+ } | |
+ else | |
+ { | |
+ for ( i = 0; i < 3; i++ ) | |
+ printf ( "\033[K\n" ); | |
+ printf ( "\r\033[3A" ); | |
+ } | |
+ | |
+ /* save time */ | |
+ struct timeval end_time; | |
+ gettimeofday ( & end_time, NULL ); | |
+ int usec_elapsed = end_time.tv_usec - start_time.tv_usec; | |
+ double sec_elapsed = ( double ) usec_elapsed / 1000000.f; | |
+ sec_elapsed += ( double ) ( end_time.tv_sec - start_time.tv_sec ); | |
+ | |
+ /* get total size */ | |
+ char sTotalWritten[20]; | |
+ file_size_format ( sTotalWritten, g_iTotalSize, 1 ); | |
+ /* TODO: using g_iTotalWritten would be more correct, but is less accurate */ | |
+ | |
+ /* calculate speed */ | |
+ int copy_speed = ( int ) ( ( double ) g_iTotalWritten / sec_elapsed ); | |
+ char s_copy_speed[20]; | |
+ file_size_format ( s_copy_speed, copy_speed, 1 ); | |
+ | |
+ /* good-bye message */ | |
+ printf ( "%d files (%s) moved in %.1f seconds (%s/s).\n", g_iFilesCopied, sTotalWritten, | |
+ sec_elapsed, s_copy_speed ); | |
+ } | |
+ /* END progress mod */ | |
return ok ? EXIT_SUCCESS : EXIT_FAILURE; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment