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

Re: [PATCH] respect nullglob given multios



> On Thu, 2019-10-10 at 16:40 +0000, Peter Stephenson wrote:
>
> > On Thu, 2019-10-10 at 01:18 +0000, Joe Rice wrote:
> >
> > > This patch makes multios behave less surprisingly with nullglob.
> > > Currently, multios throws a file not found error when a nullglob is
> > > given. This patch inserts /dev/null into the redirection list when
> > > the
> > > glob returns empty with no errors.
> > > Is this a behavior that would interest anyone else? I find myself
> > > using the `cat /dev/null *(N.)` idiom quite a bit and I thought the
> > > behavior made sense for the null case in multios.
> >
> > This does seem a logical effect, though it ought to be documented.
>
> I am not sure if it's that logical.
> What about if the pipeline on left of the redirection is something
> expensive?
> I'd rather have the command fail than starting a long-running job whose
> output will be lost.

For the case of expensive pipelines on the left side, running with a global nullglob and expecting it to never be null already seems like a risky proposition, and if they were using an explicit qualifier, then I think they would have sufficiently acknowledged that behavior.

Clear acknowledgement of behavior:

% setopt nullglob
... few lines ...
% expensive > *

% expensive > *(N)

Concerning unexpected behavior:

% setopt nullglob
... many lines ...
% expensive > *

This can be addressed explicitly by toggling nullglob off on this line with (N).

> Also, conceptually, this introduces a difference between the behaviors
> of an explicitly empty redirection and an empty redirection after
> filename expansion.
>
> Compare:
> % zsh -f
> % echo $ZSH_VERSION
> 5.7.1
> % print nosuchfileprefix*(N)
>
> % print
>
> % print > nosuchfileprefix*(N) # Implicitly sends to /dev/null

I think these three are very different in the user's mind:

% print *
Should list the files in the current directory.

% print
Should print only a newline, which happens to be the same output as listing an empty directory.

% print > *
Should truncate and write a single newline to each file in the current directory.

The only difference this patch makes is that the latter now writes "to nothing" when the nullglob is enabled.

> % print >
> zsh: parse error near `\n'
>
> I'd argue that the behavior should be the same: both should send to
> /dev/null or not.

I think this is the most different, as multios doesn't have a conceptual effect on normal use of single redirections. Redirections are conceptually (#)(<|>)(target) anywhere on the line so changing behavior on multios seems odd. Consider this case:

% > * grep ...

'>' is not pulling the next resolved tokens and testing if that is empty. It's pulling the pattern and testing if that is resolves as empty.

% print >

Offers no such pattern.

> Incidentally, and as a completely separate issue, on an unpatched 5.7.1
> zsh (Fedora 30 stock package), the command above succeeds and creates a
> file:
> % print > nosuchfileprefix*(N)
> % ls nosuchfileprefix*(N)
> 'nosuchfileprefix'$'\207\210''N'$'\212'
>
> Is that expected?

That is expected with the current implementation (5.7.1), this patch would intentionally resolve it as `print > /dev/null` instead.

Another bit that seems relevant is how this patch handles brace expansion under multios:

% setopt nomultios
% empty=()
% print > ${^empty}
zsh: no such file or directory:
% setopt multios
% print > ${^empty}

Which is desirable (I think).

% ls
foo.a
% grep < *.{a,b,c}(N)

Resolves as:

% grep < {*.a(N),*.b(N),*.c(N)}
% grep < foo.a < /dev/null < /dev/null

Which should be functionally the same and seems to fit in with how brace expansion and patterns interact.

Joe



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