[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[RFC] wc: add new option, --progress
From: |
Bo Borgerson |
Subject: |
[RFC] wc: add new option, --progress |
Date: |
Fri, 31 Oct 2008 18:20:46 -0400 |
User-agent: |
Thunderbird 2.0.0.17 (X11/20080925) |
Hi,
I've recently found myself wishing for an option in 'wc' that shows
progress during an invocation. I modified my local copy with the
changes in the attached patch to accept a '--progress' option.
This patch is also available at git://repo.or.cz/coreutils/bo.git
An example of behavior can be observed with the attached 'slowrite' program:
$ ./slowrite 100000 | src/wc --progress
100000 200000 800000
$ src/wc --progress <(./slowrite 100000 3) <(./slowrite 1000000 4)
100000 200000 800000 /dev/fd/63
1000000 2000000 8000000 /dev/fd/62
1100000 2200000 8800000 total
Of course these examples don't show any difference from an ordinary wc
invocation once they're complete. ;)
Here's a view when stdout isn't attached to a terminal:
$ ./slowrite 100000 | src/wc --progress > log &
[1] 19880
$ tail -f log
8704 17408 69632
16896 33792 135168
25088 50176 200704
33792 67584 270336
41984 83968 335872
50176 100352 401408
58368 116736 466944
67072 134144 536576
75264 150528 602112
83456 166912 667648
92160 184320 737280
100000 200000 800000
Would this be useful to anyone else?
Thanks,
Bo
>From 80089c8b1d616ec3c3a88b4f58131506a5aa43f3 Mon Sep 17 00:00:00 2001
From: Bo Borgerson <address@hidden>
Date: Wed, 29 Oct 2008 11:00:06 -0400
Subject: [PATCH] wc: add new option, --progress
* src/wc.c (set_do_monitor) ALRM handler sets DO_MONITOR flag that triggers
output.
(write_counts) Unset DO_MONITOR flag. New argument, is_final, set to true for
the
final invocation for each input. If stdout is connected to a terminal, write all
counts for a single input on a single line.
(wc) Check DO_MONITOR flag in read loop and call write_counts if set.
(main) Set up an ALRM sigaction handler to call set_do_monitor.
---
src/wc.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
1 files changed, 78 insertions(+), 11 deletions(-)
diff --git a/src/wc.c b/src/wc.c
index 0bb1929..771d6f1 100644
--- a/src/wc.c
+++ b/src/wc.c
@@ -21,6 +21,7 @@
#include <stdio.h>
#include <getopt.h>
+#include <signal.h>
#include <sys/types.h>
#include <wchar.h>
#include <wctype.h>
@@ -66,6 +67,9 @@ static int number_width;
/* True if we have ever read the standard input. */
static bool have_read_stdin;
+/* Set by sig ALRM handler, triggers output at convenience. Unset at output.
*/
+static bool do_progress = false;
+
/* The result of calling fstat or stat on a file descriptor or file. */
struct fstatus
{
@@ -81,7 +85,8 @@ struct fstatus
non-character as a pseudo short option, starting with CHAR_MAX + 1. */
enum
{
- FILES0_FROM_OPTION = CHAR_MAX + 1
+ FILES0_FROM_OPTION = CHAR_MAX + 1,
+ PROGRESS_OPTION
};
static struct option const longopts[] =
@@ -92,6 +97,7 @@ static struct option const longopts[] =
{"words", no_argument, NULL, 'w'},
{"files0-from", required_argument, NULL, FILES0_FROM_OPTION},
{"max-line-length", no_argument, NULL, 'L'},
+ {"progress", no_argument, NULL, PROGRESS_OPTION},
{GETOPT_HELP_OPTION_DECL},
{GETOPT_VERSION_OPTION_DECL},
{NULL, 0, NULL, 0}
@@ -122,6 +128,7 @@ read standard input.\n\
--files0-from=F read input from the files specified by\n\
NUL-terminated names in file F\n\
-L, --max-line-length print the length of the longest line\n\
+ --progress print counts every second until complete\n\
-w, --words print the word counts\n\
"), stdout);
fputs (HELP_OPTION_DESCRIPTION, stdout);
@@ -131,6 +138,13 @@ read standard input.\n\
exit (status);
}
+static void
+set_do_progress (int sig)
+{
+ do_progress = true;
+ alarm (1);
+}
+
/* FILE is the name of the file (or NULL for standard input)
associated with the specified counters. */
static void
@@ -139,39 +153,58 @@ write_counts (uintmax_t lines,
uintmax_t chars,
uintmax_t bytes,
uintmax_t linelength,
- const char *file)
+ const char *file,
+ bool is_final)
{
static char const format_sp_int[] = " %*s";
char const *format_int = format_sp_int + 1;
char buf[INT_BUFSIZE_BOUND (uintmax_t)];
+ static size_t plen = 0;
+
+ if (0 < plen && isatty (STDOUT_FILENO))
+ {
+ size_t i;
+ for (i = 0; i < plen; i++)
+ putchar (0x08); /* Backspace. */
+ plen = 0;
+ }
if (print_lines)
{
- printf (format_int, number_width, umaxtostr (lines, buf));
+ plen += printf (format_int, number_width, umaxtostr (lines, buf));
format_int = format_sp_int;
}
if (print_words)
{
- printf (format_int, number_width, umaxtostr (words, buf));
+ plen += printf (format_int, number_width, umaxtostr (words, buf));
format_int = format_sp_int;
}
if (print_chars)
{
- printf (format_int, number_width, umaxtostr (chars, buf));
+ plen += printf (format_int, number_width, umaxtostr (chars, buf));
format_int = format_sp_int;
}
if (print_bytes)
{
- printf (format_int, number_width, umaxtostr (bytes, buf));
+ plen += printf (format_int, number_width, umaxtostr (bytes, buf));
format_int = format_sp_int;
}
if (print_linelength)
{
- printf (format_int, number_width, umaxtostr (linelength, buf));
+ plen += printf (format_int, number_width, umaxtostr (linelength, buf));
}
if (file)
- printf (" %s", file);
- putchar ('\n');
+ plen += printf (" %s", file);
+
+ if (is_final || !isatty (STDOUT_FILENO))
+ {
+ putchar ('\n');
+ plen = 0;
+ }
+ if (!is_final)
+ fflush (stdout);
+
+ do_progress = false;
}
/* Count words. FILE_X is the name of the file (or NULL for standard
@@ -241,6 +274,10 @@ wc (int fd, char const *file_x, struct fstatus *fstatus)
break;
}
bytes += bytes_read;
+
+ if (do_progress)
+ write_counts (lines, words, chars, bytes, linelength, file_x,
+ false);
}
}
}
@@ -265,6 +302,9 @@ wc (int fd, char const *file_x, struct fstatus *fstatus)
++lines;
}
bytes += bytes_read;
+
+ if (do_progress)
+ write_counts (lines, words, chars, bytes, linelength, file_x,
false);
}
}
#if HAVE_MBRTOWC && (MB_LEN_MAX > 1)
@@ -401,6 +441,8 @@ wc (int fd, char const *file_x, struct fstatus *fstatus)
}
prev = bytes_read;
# endif
+ if (do_progress)
+ write_counts (lines, words, chars, bytes, linelength, file_x,
false);
}
if (linepos > linelength)
linelength = linepos;
@@ -459,6 +501,9 @@ wc (int fd, char const *file_x, struct fstatus *fstatus)
}
}
while (--bytes_read);
+
+ if (do_progress)
+ write_counts (lines, words, chars, bytes, linelength, file_x,
false);
}
if (linepos > linelength)
linelength = linepos;
@@ -468,7 +513,7 @@ wc (int fd, char const *file_x, struct fstatus *fstatus)
if (count_chars < print_chars)
chars = bytes;
- write_counts (lines, words, chars, bytes, linelength, file_x);
+ write_counts (lines, words, chars, bytes, linelength, file_x, true);
total_lines += lines;
total_words += words;
total_chars += chars;
@@ -623,6 +668,10 @@ main (int argc, char **argv)
files_from = optarg;
break;
+ case PROGRESS_OPTION:
+ do_progress = true;
+ break;
+
case_GETOPT_HELP_CHAR;
case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
@@ -679,6 +728,24 @@ main (int argc, char **argv)
fstatus = get_input_fstatus (nfiles, files);
number_width = compute_number_width (nfiles, fstatus);
+ if (do_progress)
+ {
+ struct sigaction alarm_handler;
+
+ sigemptyset (&alarm_handler.sa_mask);
+
+ alarm_handler.sa_handler = set_do_progress;
+
+ alarm_handler.sa_flags = SA_RESTART;
+
+ sigaction (SIGALRM, &alarm_handler, NULL);
+
+ alarm (1);
+
+ /* This will be set again in one second by SET_DO_PROGRESS. */
+ do_progress = false;
+ }
+
ok = true;
for (i = 0; i < nfiles; i++)
{
@@ -720,7 +787,7 @@ main (int argc, char **argv)
if (1 < nfiles)
write_counts (total_lines, total_words, total_chars, total_bytes,
- max_line_length, _("total"));
+ max_line_length, _("total"), true);
free (fstatus);
--
1.5.4.3
#!/usr/bin/perl -w
use strict;
my ($n, $s) = @ARGV;
$n or die "usage: $0 RECORDS [SECONDS]\n";
$s ||= 10;
my $m = $n / 100 / $s;
$m < 2 and $m = 2;
for (1..$n){
print "foo bar\n";
($_ % $m) == 1 and select (undef, undef, undef, 0.01);
}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [RFC] wc: add new option, --progress,
Bo Borgerson <=