zsh-users
 help / color / mirror / code / Atom feed
* Recursive globbing shorthand (a la **.c)
@ 2015-10-28  6:57 Dominik Vogt
  2015-10-28 13:27 ` Mikael Magnusson
  2015-10-29 10:53 ` Peter Stephenson
  0 siblings, 2 replies; 6+ messages in thread
From: Dominik Vogt @ 2015-10-28  6:57 UTC (permalink / raw)
  To: Zsh Users

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

as a shorthand, and the "traditional" uses would work without
change (e.g. **/*.c or **/foo).

(Note that on German keyboards, "/" and "*" are very awkward to
type in a sequence because both need the left shift key held and
the keys for the right hand are very far apart, so this is really
a usability issue.)

Ciao

Dominik ^_^  ^_^


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Recursive globbing shorthand (a la **.c)
  2015-10-28  6:57 Recursive globbing shorthand (a la **.c) Dominik Vogt
@ 2015-10-28 13:27 ` Mikael Magnusson
  2015-10-28 19:04   ` ZyX
                     ` (2 more replies)
  2015-10-29 10:53 ` Peter Stephenson
  1 sibling, 3 replies; 6+ messages in thread
From: Mikael Magnusson @ 2015-10-28 13:27 UTC (permalink / raw)
  To: vogt, Zsh Users

On Wed, Oct 28, 2015 at 7:57 AM, Dominik Vogt <vogt@linux.vnet.ibm.com> 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
>
> as a shorthand, and the "traditional" uses would work without
> change (e.g. **/*.c or **/foo).
>
> (Note that on German keyboards, "/" and "*" are very awkward to
> type in a sequence because both need the left shift key held and
> the keys for the right hand are very far apart, so this is really
> a usability issue.)

If this is something you do often, you can do
alias -g '**.c=**/*.c'

I don't think it's useful to implement generally though, there's no
particular reason to assume the pattern following the **/ should start
with a *

-- 
Mikael Magnusson


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Recursive globbing shorthand (a la **.c)
  2015-10-28 13:27 ` Mikael Magnusson
@ 2015-10-28 19:04   ` ZyX
       [not found]   ` <240121446059044__35603.2418822453$1446059490$gmane$org@web30h.yandex.ru>
  2015-10-29 10:15   ` Dominik Vogt
  2 siblings, 0 replies; 6+ messages in thread
From: ZyX @ 2015-10-28 19:04 UTC (permalink / raw)
  To: Mikael Magnusson, vogt, Zsh Users

28.10.2015, 16:28, "Mikael Magnusson" <mikachu@gmail.com>:
> On Wed, Oct 28, 2015 at 7:57 AM, Dominik Vogt <vogt@linux.vnet.ibm.com> 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
>>
>>  as a shorthand, and the "traditional" uses would work without
>>  change (e.g. **/*.c or **/foo).
>>
>>  (Note that on German keyboards, "/" and "*" are very awkward to
>>  type in a sequence because both need the left shift key held and
>>  the keys for the right hand are very far apart, so this is really
>>  a usability issue.)
>
> If this is something you do often, you can do
> alias -g '**.c=**/*.c'
>
> I don't think it's useful to implement generally though, there's no
> particular reason to assume the pattern following the **/ should start
> with a *

This depends on how you treat patterns. In mercurial `**` is treated as `.*` and `*` is treated as `[^/]*`, so pattern `a**b` matches file `a/c/b` (note. With such interpretation transforming foo** into foo*/**, **bar into **/*bar and foo**bar into foo*/**/*bar makes perfect sense. Though mercurial is using regexps on a list of files, not the real globbing, this behaviour is official and not an accident: there are patterns like `**.c` in examples. As OP said this is convenient in many cases.

// And git documentation officially says that only valid uses of `**` are `…/**`, `**/…` and `…/**/…`.

>
> --
> Mikael Magnusson


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Recursive globbing shorthand (a la **.c)
       [not found]   ` <240121446059044__35603.2418822453$1446059490$gmane$org@web30h.yandex.ru>
@ 2015-10-28 21:15     ` Stephane Chazelas
  0 siblings, 0 replies; 6+ messages in thread
From: Stephane Chazelas @ 2015-10-28 21:15 UTC (permalink / raw)
  To: ZyX; +Cc: Mikael Magnusson, vogt, Zsh Users

2015-10-28 22:04:04 +0300, ZyX:
[...]
> This depends on how you treat patterns. In mercurial `**` is
> treated as `.*` and `*` is treated as `[^/]*`, so pattern
> `a**b` matches file `a/c/b` (note. With such interpretation
> transforming foo** into foo*/**, **bar into **/*bar and
> foo**bar into foo*/**/*bar makes perfect sense. Though
> mercurial is using regexps on a list of files, not the real
> globbing, this behaviour is official and not an accident:
> there are patterns like `**.c` in examples. As OP said this is
> convenient in many cases.
[...]

That's also the behaviour of globbing in the  fish shell.

That means that for instance you cannot match dot files (or any
pattern matching on the beggining of the file in fish.

For zsh's **/.*, in fish you'd need both .* and **/.*

I prefer zsh behaviour.

ksh93, bash and tcsh support ** alone, but not **.c

See also
http://unix.stackexchange.com/questions/62660/the-result-of-ls-ls-and-ls/62665#62665

BTW, a related question:

In zsh (also in yash and tcsh now), *** is the version of **
that traverses symlinks.

Also,

*.d/foo

traverses symlinks,

(*.d)#/foo

doesn't

** is short for (*/)#

Is there a way to do */foo without traversing symlinks (other
than l=(*(/N)); l=($^l/foo(N)); (($#l)) && cmd $l)?

(*/)(#c1)foo doesn't work

Or (^.svn/)#foo.c that traverses symlinks?

-- 
Stephane



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Recursive globbing shorthand (a la **.c)
  2015-10-28 13:27 ` Mikael Magnusson
  2015-10-28 19:04   ` ZyX
       [not found]   ` <240121446059044__35603.2418822453$1446059490$gmane$org@web30h.yandex.ru>
@ 2015-10-29 10:15   ` Dominik Vogt
  2 siblings, 0 replies; 6+ messages in thread
From: Dominik Vogt @ 2015-10-29 10:15 UTC (permalink / raw)
  To: Zsh Users

On Wed, Oct 28, 2015 at 02:27:38PM +0100, Mikael Magnusson wrote:
> If this is something you do often, you can do
> alias -g '**.c=**/*.c'

It *is* something I do a lot, but with varying patterns.  A kind
of "regexp" alias woud allow that:

  alias -R REGEXP=REPLACEMENT   # usual regexp syntax plus back references
  alias -g -R [.][.][.]='../..'
  alias -g -R [*][*]\([^*/]\)='**/*\1'

(or give up the pretense that "search and replace" can be
expressed as "x=y" patterns:

  alias -g -R 's:[.][.][.]:../..:g'       # replace all (g flag)
  alias -g -R 's:[*][*]([^*/]):**/*\1:'   # replace one (no flags)
)

I frequently miss such a feature that allows some user defined
preprocessing of command lines.

Dominik ^_^  ^_^

-- 

Dominik Vogt
IBM Germany


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Recursive globbing shorthand (a la **.c)
  2015-10-28  6:57 Recursive globbing shorthand (a la **.c) Dominik Vogt
  2015-10-28 13:27 ` Mikael Magnusson
@ 2015-10-29 10:53 ` Peter Stephenson
  1 sibling, 0 replies; 6+ messages in thread
From: Peter Stephenson @ 2015-10-29 10:53 UTC (permalink / raw)
  To: Zsh Users

On Wed, 28 Oct 2015 07:57:02 +0100
Dominik Vogt <vogt@linux.vnet.ibm.com> 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,


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2015-10-29 10:53 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-10-28  6:57 Recursive globbing shorthand (a la **.c) Dominik Vogt
2015-10-28 13:27 ` Mikael Magnusson
2015-10-28 19:04   ` ZyX
     [not found]   ` <240121446059044__35603.2418822453$1446059490$gmane$org@web30h.yandex.ru>
2015-10-28 21:15     ` Stephane Chazelas
2015-10-29 10:15   ` Dominik Vogt
2015-10-29 10:53 ` Peter Stephenson

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).