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

Re: Any way to allow clobbering empty files when noclobber is set?

Bart Schaefer wrote on Wed, 03 Jun 2020 22:00 -0700:
> On Wed, Jun 3, 2020 at 9:06 PM Daniel Shahaf <d.s@xxxxxxxxxxxxxxxxxx> wrote:>
> >
> > [ Let's call this UNLINK_EMPTY_AFTER_FAILURE for the sake of discussion. ]
> >
> > Bart Schaefer wrote on Thu, 04 Jun 2020 02:43 +00:00:  
> > >
> > > How does that user experience differ from HIST_ALLOW_CLOBBER?  
> >
> > Well, for one, because that proposal only takes effect when foo exited
> > non-zero, created bar, and bar is zero-sized?  
> Fair enough, although (silly example) "false > empty" would remove the
> file?

Depends on whether ./empty was created by the redirection or not.  Files
would only be removed if they were created by the redirection operator:

    % cd "$(mktemp -d)"
    % ls
    % false > empty
    % ls
    % touch empty
    % false > empty
    % ls

> Wouldn't you at least want the reason for the unlink to be that the
> redirection failed, rather than that the command exited non-zero?

I was thinking that if the command exited non-zero and didn't write
anything to stdout, then presumably the file was expected to contain
something and is of no use otherwise.  This rule DTRT's for diff(1), for
example, despite that command exiting non-zero even in some non-error cases.

Besides, if the redirection failed — I assume you mean the open(2)
failed — then isn't the unlink likely to fail as well?

> What if the redirection target is a symbolic link?  What if it isn't a
> plain file?

Again, the sequence of events is:

1. bar doesn't exist.
2. Run «foo > bar».  As part of this, we create bar as a zero-length plain file.
3. The exit code is non-zero.
4. We stat() bar to see if it's zero-length.

If in step #4 we find that bar is not even a plain file, we'll infer
that some other process has to have unlinked the plain file we created
in step 2, and we'll leave bar alone.

> > > and silently unlinking a file is not very friendly.  The /etc/nologin
> > > example in your next message comes to mind.  
> >
> > Doesn't this argument also apply to anyone who might set CLOBBER_EMPTY
> > and then lose the timestamps on empty files, as in your next message?  
> Yes, but to a lesser degree, because the file is at least still
> present if it's presence means something.

Okay.  Is there a case where leaving around an empty file is worse than
removing it?  Consider, for example, «curl -o- http://example.com/pre-repvrop-change > hooks/pre-revprop-change»
in a Subversion repository.  The URL is misspelled, so the command will
create an empty pre-revprop-change file, which will allow non-undoable
changes to be made.  Furthermore, if the command had succeeded, only
some such changes would have been allowed; and if the file had not
existed, no such changes would have been allowed.  Given these
semantics, a sysadmin might well prefer to have _no_ pre-revprop-change
file rather than to have an empty one.

Another example: if I do «diff lorem ipsum > bar» and some other process
periodically polls whether bar has been created, the waiting process
might take an empty file to mean there's no difference between lorem and
ipsum.  In this situation, too, it might be better to unlink bar than to
leave it around empty.  (This could be made less contrived by changing
the scenario to someone copying a command from the output of `make -n`
and pasting it at the interactive prompt.  make(1) targets is another
case where empty files and non-existing files behave differently.)

Or perhaps something along the lines of «tar cf - foo > foo.tar; xz
foo.tar» in a single command line.  (Not a good example, though, since
here the user could've used «&&».)



P.S.  In the pre-revprop-change example, the sysadmin should have
downloaded the file to a temporary name and then atomically renamed it
into place.  Some syntactic sugar for this pattern this might be nice…

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