zsh-users
 help / color / mirror / code / Atom feed
* Better ( rm foo; bar > foo ) < foo ?
@ 2000-12-03 14:01 Hannu Koivisto
  2000-12-03 17:48 ` Bart Schaefer
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Hannu Koivisto @ 2000-12-03 14:01 UTC (permalink / raw)
  To: Zsh Users' List

Greetings,

If I needed to, say, modify some file with sed in a script, I'd
probably write something like this:

TMPFILE=$(mktemp "$(dirname "$FILE")/XXXXXX") || exit 1
sed 's/foo/bar/g' < "$FILE" > "$TMPFILE" || { rm -f "$TMPFILE" ; exit 1 }
mv "$TMPFILE" "$FILE"

This is quite clumsy (even if I removed some of the safety) and
thus the trick shown on the subject is quite appealing especially
in interactive use.  Unfortunately it has the problem that if bar
fails, the data is lost.  Besides, even it is a bit clumsier than
I'd like.

So, I started to ponder if zsh could help here.  Unfortunately I
couldn't come up with any nice "wrapping" of the functionality
above with a function or other existing zsh features, only a
thought of whether it would be possible to create some sort of new
redirection syntax that would do the trick.

What do you think?

-- 
Hannu


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

* Re: Better ( rm foo; bar > foo ) < foo ?
  2000-12-03 14:01 Better ( rm foo; bar > foo ) < foo ? Hannu Koivisto
@ 2000-12-03 17:48 ` Bart Schaefer
  2000-12-03 23:17   ` Hannu Koivisto
  2000-12-03 20:24 ` Clint Adams
  2000-12-07 11:44 ` Danny Dulai
  2 siblings, 1 reply; 8+ messages in thread
From: Bart Schaefer @ 2000-12-03 17:48 UTC (permalink / raw)
  To: Hannu Koivisto, Zsh Users' List

How about

	mv -i =(bar < foo) foo

??  As long as `bar' produces some kind of failure output, that should be OK
for interactive use.

A little more input on what you think would NOT be clumsy would help.  For
example, would

	rewrite sed 's/foo/bar/g' foo

be OK?  Just take your original "in a script, I'd probably write" and put
it in a function:

    rewrite() {
	local TMPFILE=${TMPPREFIX}rewrite.$$	# Whatever
	$argv[1,-2] < $argv[-1] > $TMPFILE || rm -f $TMPFILE
	[[ -f $TMPFILE ]] && mv -f $TMPFILE $argv[-1]
    }

You can probably figure out what to do if you'd prefer the syntax

	rewrite foo sed 's/foo/bar/g'

instead ...

-- 
Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com

Zsh: http://www.zsh.org | PHPerl Project: http://phperl.sourceforge.net   


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

* Re: Better ( rm foo; bar > foo ) < foo ?
  2000-12-03 14:01 Better ( rm foo; bar > foo ) < foo ? Hannu Koivisto
  2000-12-03 17:48 ` Bart Schaefer
@ 2000-12-03 20:24 ` Clint Adams
  2000-12-07 11:44 ` Danny Dulai
  2 siblings, 0 replies; 8+ messages in thread
From: Clint Adams @ 2000-12-03 20:24 UTC (permalink / raw)
  To: zsh-users

> TMPFILE=$(mktemp "$(dirname "$FILE")/XXXXXX") || exit 1
> sed 's/foo/bar/g' < "$FILE" > "$TMPFILE" || { rm -f "$TMPFILE" ; exit 1 }
> mv "$TMPFILE" "$FILE"

I find that

perl -pi -e 's/foo/bar/g' $FILE

is much less of a hassle, if that's the complexity you're dealing with.


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

* Re: Better ( rm foo; bar > foo ) < foo ?
  2000-12-03 17:48 ` Bart Schaefer
@ 2000-12-03 23:17   ` Hannu Koivisto
  2000-12-04  2:27     ` Bart Schaefer
  0 siblings, 1 reply; 8+ messages in thread
From: Hannu Koivisto @ 2000-12-03 23:17 UTC (permalink / raw)
  To: Zsh Users' List

"Bart Schaefer" <schaefer@candle.brasslantern.com> writes:

| How about
| 
| 	mv -i =(bar < foo) foo

At first I thought this is cool and very close to what I was
looking for but...

| ??  As long as `bar' produces some kind of failure output, that should be OK

...it seems you mean I have to have that -i there and wait and see
if bar says something went wrong and then tell mv not to
overwrite.  A little test seems to indicate this is indeed how =()
works, i.e. without -i it would run mv even if bar returns false.
I think I prefer your rewrite suggestion below.

| A little more input on what you think would NOT be clumsy would help.  For

That three-liner I wrote is too clumsy for throw-away-scripting; I
guess I was fantasizing about something like
sed 's/foo/bar/g' <> foo (with something else in place of <> since
that seems to be in use already) but I think anything that keeps
one-liners as one-liners is ok, like that rewrite below.

| example, would
| 
| 	rewrite sed 's/foo/bar/g' foo
| be OK?  Just take your original "in a script, I'd probably write" and put

It would be ok.

| it in a function:
| 
|     rewrite() {
| 	local TMPFILE=${TMPPREFIX}rewrite.$$	# Whatever
| 	$argv[1,-2] < $argv[-1] > $TMPFILE || rm -f $TMPFILE
| 	[[ -f $TMPFILE ]] && mv -f $TMPFILE $argv[-1]
|     }

Thanks, this is what I thought of first too, but I got greedy and I
wanted the hypothetical ideal way to work so that I could also
redirect the output to another place at the same time,
i.e. something like sed 's/foo/bar/g' <> foo > bar | baz and I
couldn't figure out how to include that to such function-approach
as rewrite, so I dropped the idea, but, well, I guess that rewrite
is just fine after all.

Clint Adams <schizo@debian.org> writes:

| I find that
| 
| perl -pi -e 's/foo/bar/g' $FILE
| 
| is much less of a hassle, if that's the complexity you're dealing with.

I find that Perl equals to pain, so I try to avoid it any way I
can (fortunately there is no Perl for my new machine, I think) :)
In any case, that sed thing was just an example, I was trying to
find a general way.

Thanks anyway,
-- 
Hannu


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

* Re: Better ( rm foo; bar > foo ) < foo ?
  2000-12-03 23:17   ` Hannu Koivisto
@ 2000-12-04  2:27     ` Bart Schaefer
  0 siblings, 0 replies; 8+ messages in thread
From: Bart Schaefer @ 2000-12-04  2:27 UTC (permalink / raw)
  To: Hannu Koivisto, Zsh Users' List

On Dec 4,  1:17am, Hannu Koivisto wrote:
} Subject: Re: Better ( rm foo; bar > foo ) < foo ?
}
} "Bart Schaefer" <schaefer@candle.brasslantern.com> writes:
} | 	mv -i =(bar < foo) foo
} 
} ...it seems you mean I have to have that -i there and wait and see
} if bar says something went wrong and then tell mv not to
} overwrite.  [...] I think I prefer your rewrite suggestion below.
} 
} I was fantasizing about something like sed 's/foo/bar/g' <> foo (with
} something else in place of <> since that seems to be in use already)

Yes, <> means "open for both reading and writing," which is sometimes
useful as it's the mode in which stdin/out/err are typically opened on
a terminal.  The implicit descriptor to the left of <> is 0, so unless
you supply another number it opens stdin.

If you give a descriptor number, you can use <> to open a file for
overwrite-without-truncation:

    zsh% print "foo\nbar" >| foo
    zsh% <foo
    foo
    bar
    zsh% print xxx 1<>foo
    zsh% <foo
    xxx
    bar

So if you know that e.g. sed is either going to fail to produce any output
at all, or will succeed with exactly as much output as the length of the
original input, you can do

    sed 's/foo/bar/g' <foo 1<>foo

But this is pretty dangerous because if sed ever writes more bytes than it
has already read, it'll start re-reading what it wrote.

} I wanted the hypothetical ideal way to work so that I could also
} redirect the output to another place at the same time,
} i.e. something like sed 's/foo/bar/g' <> foo > bar | baz

What output do you want in bar and piped to baz when the command fails?
Nothing?  The original contents of foo?  (Below, I'll guess "nothing.")

There's always

    X==(<foo) eval 'sed "s/foo/bar/g" < $X >| foo || < $X >| foo'

In which case you can insert your other redirections wherever they'd be
appropriate.  It's actually important that that's a one-liner; if it
were not, zsh would remove the temp file whose name is assigned to $X
before it could be read by sed.

Hence a shorter version of "rewrite" if you don't mind copying the input
file either twice (on success) or three times (on failure):

    rewrite() {
	local O=$@[-1]
	I==(<$O) eval '$@[1,-2] <$I >|$O || { <$I >|$O && ((0)) }'
    }

(The ((0)) is just a cute way to write "false".)

Add one more thing to get the rewritten file on stdout when the command
succeeds:

    rewrite() {
	local O=$@[-1]
	I==(<$O) eval '$@[1,-2] <$I >|$O || { <$I >|$O && ((0)) }' && <$O
    }

And now you can say

    rewrite sed "s/foo/bar/g" foo > bar | baz

OK?


-- 
Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com

Zsh: http://www.zsh.org | PHPerl Project: http://phperl.sourceforge.net   


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

* Re: Better ( rm foo; bar > foo ) < foo ?
  2000-12-03 14:01 Better ( rm foo; bar > foo ) < foo ? Hannu Koivisto
  2000-12-03 17:48 ` Bart Schaefer
  2000-12-03 20:24 ` Clint Adams
@ 2000-12-07 11:44 ` Danny Dulai
  2000-12-07 14:17   ` Andrej Borsenkow
  2 siblings, 1 reply; 8+ messages in thread
From: Danny Dulai @ 2000-12-07 11:44 UTC (permalink / raw)
  To: Hannu Koivisto, Zsh Users' List

On 12/03/00, Hannu Koivisto said:
>Greetings,
>
>If I needed to, say, modify some file with sed in a script, I'd
>probably write something like this:
>
>TMPFILE=$(mktemp "$(dirname "$FILE")/XXXXXX") || exit 1
>sed 's/foo/bar/g' < "$FILE" > "$TMPFILE" || { rm -f "$TMPFILE" ; exit 1 }
>mv "$TMPFILE" "$FILE"
>
>This is quite clumsy (even if I removed some of the safety) and
>thus the trick shown on the subject is quite appealing especially
>in interactive use.  Unfortunately it has the problem that if bar
>fails, the data is lost.  Besides, even it is a bit clumsier than
>I'd like.
>
>So, I started to ponder if zsh could help here.  Unfortunately I
>couldn't come up with any nice "wrapping" of the functionality
>above with a function or other existing zsh features, only a
>thought of whether it would be possible to create some sort of new
>redirection syntax that would do the trick.
>
>What do you think?
>
>-- 
>Hannu
>

% cat foo
one
% mv =(sed 's/one/two/' foo) foo
% cat foo
two

hows that?

-- 
___________________________________________________________________________
Danny Dulai                                           Feet. Pumice. Lotion.
http://www.ishiboo.com/~nirva/                            nirva@ishiboo.com


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

* RE: Better ( rm foo; bar > foo ) < foo ?
  2000-12-07 11:44 ` Danny Dulai
@ 2000-12-07 14:17   ` Andrej Borsenkow
  2000-12-07 17:10     ` Bart Schaefer
  0 siblings, 1 reply; 8+ messages in thread
From: Andrej Borsenkow @ 2000-12-07 14:17 UTC (permalink / raw)
  To: Danny Dulai, Hannu Koivisto, Zsh Users' List


>
> % cat foo
> one
> % mv =(sed 's/one/two/' foo) foo
> % cat foo
> two
>
> hows that?

Process substitutions are executed asynchronously. So, you are just lucky to
have small file. This particular example would work even in case of big file,
because sed still has original file opened even after it has been renamed. But
in general case you may have unexpected side effects ... something like

mv =(grep one foo; grep two foo) foo

second grep most probably will catch wrong file.

-andrej


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

* Re: Better ( rm foo; bar > foo ) < foo ?
  2000-12-07 14:17   ` Andrej Borsenkow
@ 2000-12-07 17:10     ` Bart Schaefer
  0 siblings, 0 replies; 8+ messages in thread
From: Bart Schaefer @ 2000-12-07 17:10 UTC (permalink / raw)
  To: Andrej Borsenkow, Danny Dulai, Zsh Users' List

On Dec 7,  5:17pm, Andrej Borsenkow wrote:
}
} Process substitutions are executed asynchronously. [...]
} 
} mv =(grep one foo; grep two foo) foo
} 
} second grep most probably will catch wrong file.

The original question wanted stdin redirected from the file, so it could
by definition not be read twice.  In that case =(...) is "safe", except
for the case where the async command fails and the original file is lost
(which is why I suggested "mv -i" a couple of days ago).

-- 
Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com

Zsh: http://www.zsh.org | PHPerl Project: http://phperl.sourceforge.net   


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

end of thread, other threads:[~2000-12-07 17:29 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2000-12-03 14:01 Better ( rm foo; bar > foo ) < foo ? Hannu Koivisto
2000-12-03 17:48 ` Bart Schaefer
2000-12-03 23:17   ` Hannu Koivisto
2000-12-04  2:27     ` Bart Schaefer
2000-12-03 20:24 ` Clint Adams
2000-12-07 11:44 ` Danny Dulai
2000-12-07 14:17   ` Andrej Borsenkow
2000-12-07 17:10     ` 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).