Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: Recursive globbing shorthand (a la **.c)



On Wed, 28 Oct 2015 07:57:02 +0100
Dominik Vogt <vogt@xxxxxxxxxxxxxxxxxx> wrote:
> Most of the time, I use recursive globbing to find files of
> certain types, e.g.
> 
>   $ ll **/*.c
> 
> With the zsh here (4.3.17), recursive globbing works only
> with a plain ** anyway (i.e. in "**x" and "x**" the ** works just
> like a plain "*").  So, is it possible (or a useful future
> feature) to make "**" imply a trailing "/*" if not with a trailing
> pattern?  Then we could type
> 
>   $ ll **.c

It turns out this is pretty trivial to implement as an option which I've
called GLOBSTARSHORT.  No documentation yet.  It's trivial enough that I
doubt this would be problematic to include.

pws

diff --git a/Src/glob.c b/Src/glob.c
index 24e60d0..51ffeb5 100644
--- a/Src/glob.c
+++ b/Src/glob.c
@@ -682,25 +682,32 @@ parsecomplist(char *instr)
     char *str;
     int compflags = gf_noglobdots ? (PAT_FILE|PAT_NOGLD) : PAT_FILE;
 
-    if (instr[0] == Star && instr[1] == Star &&
-        (instr[2] == '/' || (instr[2] == Star && instr[3] == '/'))) {
-	/* Match any number of directories. */
-	int follow;
-
-	/* with three stars, follow symbolic links */
-	follow = (instr[2] == Star);
-	instr += (3 + follow);
-
-	/* Now get the next path component if there is one. */
-	l1 = (Complist) zhalloc(sizeof *l1);
-	if ((l1->next = parsecomplist(instr)) == NULL) {
-	    errflag |= ERRFLAG_ERROR;
-	    return NULL;
+    if (instr[0] == Star && instr[1] == Star) {
+	int shortglob = 0;
+        if (instr[2] == '/' || (instr[2] == Star && instr[3] == '/')
+	    || (shortglob = isset(GLOBSTARSHORT))) {
+	    /* Match any number of directories. */
+	    int follow;
+
+	    /* with three stars, follow symbolic links */
+	    follow = (instr[2] == Star);
+	    /*
+	     * With GLOBSTARSHORT, leave a star in place for the
+	     * pattern inside the directory.
+	     */
+	    instr += ((shortglob ? 1 : 3) + follow);
+
+	    /* Now get the next path component if there is one. */
+	    l1 = (Complist) zhalloc(sizeof *l1);
+	    if ((l1->next = parsecomplist(instr)) == NULL) {
+		errflag |= ERRFLAG_ERROR;
+		return NULL;
+	    }
+	    l1->pat = patcompile(NULL, compflags | PAT_ANY, NULL);
+	    l1->closure = 1;		/* ...zero or more times. */
+	    l1->follow = follow;
+	    return l1;
 	}
-	l1->pat = patcompile(NULL, compflags | PAT_ANY, NULL);
-	l1->closure = 1;		/* ...zero or more times. */
-	l1->follow = follow;
-	return l1;
     }
 
     /* Parse repeated directories such as (dir/)# and (dir/)## */
diff --git a/Src/options.c b/Src/options.c
index 1fb102f..3bf9f39 100644
--- a/Src/options.c
+++ b/Src/options.c
@@ -140,6 +140,7 @@ static struct optname optns[] = {
 {{NULL, "globassign",	      OPT_EMULATE|OPT_CSH},	 GLOBASSIGN},
 {{NULL, "globcomplete",	      0},			 GLOBCOMPLETE},
 {{NULL, "globdots",	      OPT_EMULATE},		 GLOBDOTS},
+{{NULL, "globstarshort",      OPT_EMULATE},		 GLOBSTARSHORT},
 {{NULL, "globsubst",	      OPT_EMULATE|OPT_NONZSH},	 GLOBSUBST},
 {{NULL, "hashcmds",	      OPT_ALL},			 HASHCMDS},
 {{NULL, "hashdirs",	      OPT_ALL},			 HASHDIRS},
diff --git a/Src/zsh.h b/Src/zsh.h
index f819249..a600105 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -2218,6 +2218,7 @@ enum {
     GLOBASSIGN,
     GLOBCOMPLETE,
     GLOBDOTS,
+    GLOBSTARSHORT,
     GLOBSUBST,
     HASHCMDS,
     HASHDIRS,



Messages sorted by: Reverse Date, Date, Thread, Author