zsh-users
 help / color / mirror / code / Atom feed
* Use glob patterns while reading a file
@ 2018-11-08 22:53 ` Dominik Ritter
  2018-11-09  9:35   ` Peter Stephenson
  0 siblings, 1 reply; 7+ messages in thread
From: Dominik Ritter @ 2018-11-08 22:53 UTC (permalink / raw)
  To: zsh-users

[-- Attachment #1: Type: text/plain, Size: 523 bytes --]

Hi all!

I want to use read one of two files, regardless if it exists or not. My
first approach is to use the alternative glob syntax, but with no luck:
$(< ./(a|b)(N))

Without the subshell, the glob is expanded first, thus it works:
< ./(a|b)(N)

Is it possible to get this to work in conjunction with a subshell?

The usual workarounds are to expand the glob first, and iterate over the
resulting files, test for existance and finally read the contents. This
seems quite cumbersome to me.

Thanks for your help,
Dominik

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

* Re: Use glob patterns while reading a file
  2018-11-08 22:53 ` Use glob patterns while reading a file Dominik Ritter
@ 2018-11-09  9:35   ` Peter Stephenson
  2018-11-09 14:37     ` Dominik Ritter
  2018-11-10  1:21     ` Daniel Shahaf
  0 siblings, 2 replies; 7+ messages in thread
From: Peter Stephenson @ 2018-11-09  9:35 UTC (permalink / raw)
  To: zsh-users

On Thu, 2018-11-08 at 23:53 +0100, Dominik Ritter wrote:
> I want to use read one of two files, regardless if it exists or not. My
> first approach is to use the alternative glob syntax, but with no luck:
> $(< ./(a|b)(N))

That's a special syntax, expecting a single file so that it doesn't try
to do globbing.

You can get it to work with

$(cat <./(a|b)(N))

pws


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

* Re: Use glob patterns while reading a file
  2018-11-09  9:35   ` Peter Stephenson
@ 2018-11-09 14:37     ` Dominik Ritter
  2018-11-09 16:20       ` Peter Stephenson
  2018-11-10  1:21     ` Daniel Shahaf
  1 sibling, 1 reply; 7+ messages in thread
From: Dominik Ritter @ 2018-11-09 14:37 UTC (permalink / raw)
  To: p.stephenson; +Cc: zsh-users

[-- Attachment #1: Type: text/plain, Size: 1464 bytes --]

I was hoping for a solution without externals. The cat version seems to be
slower than the other one, and I the null glob seems not to work, if
neither of the files was found..

Testing 10000 iterations of cat-glob
( repeat $ITERATIONS; do; echo $(cat < ./(a|b)(N) 2>/dev/null ) > /dev/null
2)  5,75s user 2,61s system 107% cpu 7,741 total
Testing 10000 iterations of resolve-first glob
( repeat $ITERATIONS; do; local -a files; files=(./(a|b)(N)) ; for file in
; )  0,11s user 0,16s system 98% cpu 0,276 total

With "b" being a simple text file.

Test-Script:
#!/bin/zsh

ITERATIONS=10000

echo "Testing $ITERATIONS iterations of cat-glob"
time (repeat $ITERATIONS; do;
        echo $(cat < ./(a|b)(N) 2>/dev/null ) >/dev/null 2>&1
done;)

echo "Testing $ITERATIONS iterations of resolve-first glob"
time (repeat $ITERATIONS; do;
        local -a files
        files=( ./(a|b)(N) )

        for file in $files; do;
                echo $(< ${file} ) >/dev/null
        done
done;)

Am Fr., 9. Nov. 2018 um 10:36 Uhr schrieb Peter Stephenson <
p.stephenson@samsung.com>:

> On Thu, 2018-11-08 at 23:53 +0100, Dominik Ritter wrote:
> > I want to use read one of two files, regardless if it exists or not. My
> > first approach is to use the alternative glob syntax, but with no luck:
> > $(< ./(a|b)(N))
>
> That's a special syntax, expecting a single file so that it doesn't try
> to do globbing.
>
> You can get it to work with
>
> $(cat <./(a|b)(N))
>
> pws
>
>

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

* Re: Use glob patterns while reading a file
  2018-11-09 14:37     ` Dominik Ritter
@ 2018-11-09 16:20       ` Peter Stephenson
  0 siblings, 0 replies; 7+ messages in thread
From: Peter Stephenson @ 2018-11-09 16:20 UTC (permalink / raw)
  To: Zsh Users' List

On Fri, 2018-11-09 at 15:37 +0100, Dominik Ritter wrote:
> I was hoping for a solution without externals. The cat version seems
> to be slower than the other one, and I the null glob seems not to
> work, if neither of the files was found..

There are various ways of outputting files from within the shell.  You
can do something like

zmodload zsh/mapfile
... $(files=(./(a|b)(N)); print -nr "$mapfile[$files[1]]")

pws


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

* Re: Use glob patterns while reading a file
  2018-11-09  9:35   ` Peter Stephenson
  2018-11-09 14:37     ` Dominik Ritter
@ 2018-11-10  1:21     ` Daniel Shahaf
  2018-11-10  2:07       ` Bart Schaefer
  1 sibling, 1 reply; 7+ messages in thread
From: Daniel Shahaf @ 2018-11-10  1:21 UTC (permalink / raw)
  To: zsh-users

Peter Stephenson wrote on Fri, 09 Nov 2018 09:35 +0000:
> On Thu, 2018-11-08 at 23:53 +0100, Dominik Ritter wrote:
> > I want to use read one of two files, regardless if it exists or not. My
> > first approach is to use the alternative glob syntax, but with no luck:
> > $(< ./(a|b)(N))
> 
> That's a special syntax, expecting a single file so that it doesn't try
> to do globbing.

I think this violates the principle of least surprise.  Grammars should be
composable and shouldn't have special cases.  The forms «foo» and
«print -r -- "$(<foo)"» should always be equivalent (assuming 'foo' outputs
a trailing newline).  Similarly, «<foo» and «<foo $READNULLCMD» are usually
equivalent, but «$(<*)» and «$(<* $READNULLCMD)» are not.

(I know that $(<foo) is optimised, but the whole point of optimisations is that
they don't change the semantics.)

By default, «*» after «<» is a glob.  There is no reason for a user to expect
«$(<*)» to be different: neither command substitution nor input redirection
implies 'noglob' or NO_MULTIOS in any other situation.

Frankly, I'm tempted to treat it as a bug — but before I jump to conclusions,
was this behaviour intentionally implemented this way?

>

The manual says:
.
    The substitution `tt($LPAR()cat) var(foo)tt(RPAR())' may be replaced
    by the equivalent but faster `tt($LPAR()<)var(foo)tt(RPAR())'.
.
which is correct only when var(foo) does not involve globbing.  I don't want to
open the user manual v. reference manual can of worms again, but I think there
is room for improvement here.

> You can get it to work with
> 
> $(cat <./(a|b)(N))

Cheers,

Daniel

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

* Re: Use glob patterns while reading a file
  2018-11-10  1:21     ` Daniel Shahaf
@ 2018-11-10  2:07       ` Bart Schaefer
  2018-11-10  2:12         ` Bart Schaefer
  0 siblings, 1 reply; 7+ messages in thread
From: Bart Schaefer @ 2018-11-10  2:07 UTC (permalink / raw)
  To: Daniel Shahaf; +Cc: Zsh Users

On Fri, Nov 9, 2018 at 5:22 PM Daniel Shahaf <d.s@daniel.shahaf.name> wrote:
>
> > > $(< ./(a|b)(N))
> >
> > That's a special syntax, expecting a single file so that it doesn't try
> > to do globbing.
>
> I think this violates the principle of least surprise.  Grammars should be
> composable and shouldn't have special cases.

Although I can't argue with this from a philosophical standpoint, I
find it astonishing to pretend that zsh ignores that philosophy only
in this particular case.

> The forms «foo» and
> «print -r -- "$(<foo)"» should always be equivalent (assuming 'foo' outputs
> a trailing newline).

I don't follow that at all.  «foo» is a shell word.  «print -r --
"$(<foo)"» is the contents of a file identified by the word «foo».  In
what context are those equivalent?

> Similarly, «<foo» and «<foo $READNULLCMD» are usually
> equivalent, but «$(<*)» and «$(<* $READNULLCMD)» are not.

The distinction here is that $(...) is a substitution, not a subshell.
It's more like a quoting mechanism (i.e. `foo`).  $(<foo) is NOT an
"optimization" of $({<foo}) (which does work exactly the way you think
it would, globbing-wise), and the "<" in that position in the
substitution is not a redirection operator, even though it looks like
one for mnemonic reasons.  $(<...) is an entirely different thing,
just like $((...)) is a different thing, even though «$(» and «<» do
not have to be composed without whitespace to form a token.

> was this behaviour intentionally implemented this way?

Yes.

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

* Re: Use glob patterns while reading a file
  2018-11-10  2:07       ` Bart Schaefer
@ 2018-11-10  2:12         ` Bart Schaefer
  0 siblings, 0 replies; 7+ messages in thread
From: Bart Schaefer @ 2018-11-10  2:12 UTC (permalink / raw)
  To: Daniel Shahaf; +Cc: Zsh Users

Just to be a little more accurate ...

On Fri, Nov 9, 2018 at 6:07 PM Bart Schaefer <schaefer@brasslantern.com> wrote:
>
> $(<...) is an entirely different thing

I should say $(<WORD) for a single WORD is a thing, and thus is
distinct from $(<WORD WORD...) where "<" becomes a redirection again.

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

end of thread, other threads:[~2018-11-10  2:13 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <CGME20181108225555epcas2p274de218aef35e46f189ebbfbd9d1892f@epcas2p2.samsung.com>
2018-11-08 22:53 ` Use glob patterns while reading a file Dominik Ritter
2018-11-09  9:35   ` Peter Stephenson
2018-11-09 14:37     ` Dominik Ritter
2018-11-09 16:20       ` Peter Stephenson
2018-11-10  1:21     ` Daniel Shahaf
2018-11-10  2:07       ` Bart Schaefer
2018-11-10  2:12         ` Bart Schaefer

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).