Hi! Suppose you have a set of files numbered and those numbers zero padded. Of course you can list them using some magic with printf or some such, but I would really love a simple feature like this:
cat x{000..123} to concatenate files x000 through x123, not x0 through x123 as bash currently does. The attached patch should do the trick. I hope you agree with the place where I chose to implement this feature. Do you think this has a chance of getting implemented into the official source tree? If so, what is left to do? Documentation? Any kind of test cases? Anything else? Greetings, Martin von Gagern P.S.: This is the second time I post this message here. The first one was via NNTP and it seems like it didn't make it.
Patch by Martin von Gagern <[EMAIL PROTECTED]> to allow zero-padded numbers in bash brace expansion sequences. diff -pur bash-3.2/braces.c bash/braces.c --- bash-3.2/braces.c 2006-09-09 04:57:17.000000000 +0200 +++ bash/braces.c 2007-08-29 23:02:02.000000000 +0200 @@ -61,7 +61,7 @@ static int brace_gobbler __P((char *, size_t, int *, int)); static char **expand_amble __P((char *, size_t, int)); static char **expand_seqterm __P((char *, size_t)); -static char **mkseq __P((int, int, int, int)); +static char **mkseq __P((int, int, int, int, int)); static char **array_concat __P((char **, char **)); #else static int brace_gobbler (); @@ -303,8 +303,8 @@ mkseq (start, end, incr, type) #define ST_CHAR 2 static char ** -mkseq (start, end, incr, type) - int start, end, incr, type; +mkseq (start, end, incr, type, width) + int start, end, incr, type, width; { int n, i; char **result, *t; @@ -329,7 +329,7 @@ mkseq (start, end, incr, type) QUIT; /* XXX - memory leak here */ #endif if (type == ST_INT) - result[i++] = itos (n); + result[i++] = itospad (n, width, '0'); else { t = (char *)xmalloc (2); @@ -353,7 +353,7 @@ expand_seqterm (text, tlen) size_t tlen; { char *t, *lhs, *rhs; - int i, lhs_t, rhs_t, lhs_v, rhs_v; + int lhs_l, rhs_l, lhs_t, rhs_t, lhs_v, rhs_v, width; intmax_t tl, tr; char **result; @@ -361,9 +361,9 @@ expand_seqterm (text, tlen) if (t == 0) return ((char **)NULL); - i = t - text; /* index of start of BRACE_SEQ_SPECIFIER */ - lhs = substring (text, 0, i); - rhs = substring (text, i + sizeof(BRACE_SEQ_SPECIFIER) - 1, tlen); + lhs_l = t - text; /* index of start of BRACE_SEQ_SPECIFIER */ + lhs = substring (text, 0, lhs_l); + rhs = substring (text, lhs_l + sizeof(BRACE_SEQ_SPECIFIER) - 1, tlen); if (lhs[0] == 0 || rhs[0] == 0) { @@ -399,9 +399,21 @@ expand_seqterm (text, tlen) { lhs_v = tl; /* integer truncation */ rhs_v = tr; + + /* find out if the user wants padding, and if so how much */ + rhs_l = tlen - lhs_l - sizeof(BRACE_SEQ_SPECIFIER) + 1; + width = 0; + if (lhs_l > 1 && lhs[0] == '0') + width = lhs_l; + if (lhs_l > 2 && lhs[0] == '-' && lhs[1] == '0') + width = lhs_l; + if (rhs_l > 1 && rhs[0] == '0' && width < rhs_l) + width = rhs_l; + if (rhs_l > 2 && rhs[0] == '-' && rhs[1] == '0' && width < rhs_l) + width = rhs_l; } - result = mkseq (lhs_v, rhs_v, 1, lhs_t); + result = mkseq (lhs_v, rhs_v, 1, lhs_t, width); free (lhs); free (rhs); diff -pur bash-3.2/externs.h bash/externs.h --- bash-3.2/externs.h 2006-07-28 03:40:49.000000000 +0200 +++ bash/externs.h 2007-08-29 22:21:16.000000000 +0200 @@ -178,6 +178,7 @@ extern char *inttostr __P((intmax_t, cha extern char *itos __P((intmax_t)); extern char *uinttostr __P((uintmax_t, char *, size_t)); extern char *uitos __P((uintmax_t)); +extern char *itospad __P((intmax_t, int, char)); /* declarations for functions defined in lib/sh/makepath.c */ #define MP_DOTILDE 0x01 diff -pur bash-3.2/lib/sh/itos.c bash/lib/sh/itos.c --- bash-3.2/lib/sh/itos.c 2002-01-02 20:38:10.000000000 +0100 +++ bash/lib/sh/itos.c 2007-08-29 23:01:01.000000000 +0200 @@ -70,3 +70,43 @@ uitos (i) p = fmtumax (i, 10, lbuf, sizeof(lbuf), FL_UNSIGNED); return (savestring (p)); } + +/* Integer to string conversion with padding. This conses the string; the + caller should free it. */ +char * +itospad (i, width, padchar) + intmax_t i; + int width; + char padchar; +{ + char *p, *buf, lbuf[INT_STRLEN_BOUND(intmax_t) + 1]; + size_t len; + + if (width + 1 <= sizeof(lbuf)) { + len = sizeof(lbuf); + buf = lbuf; + } + else { + len = width + 1; + buf = (char *)xmalloc (len); + } + + p = fmtumax (i, 10, buf, len, 0); + /* The following padding implementation relies on the fact + that fmtumax fills the buffer from its end. */ + + if (p[0] != '-') { + while (buf + len - p <= width) + *--p = padchar; + } + else { + while (buf + len - p <= width) + *p-- = padchar; + *p = '-'; + } + + if (buf == lbuf) + buf = savestring (p); + + return (buf); +}