Date: Mon, 18 Oct 2004 15:04:11 +0100 (BST) From: "Daniel Bye" <freebsd@slightlystrange.org> To: freebsd-questions@freebsd.org Subject: Re: How to run a stream based command in place on a file Message-ID: <55671.192.168.0.1.1098108251.squirrel@192.168.0.1> In-Reply-To: <200410181334.37665.rtb27@cam.ac.uk> References: <200410181334.37665.rtb27@cam.ac.uk>
index | next in thread | previous in thread | raw e-mail
On Mon, 18 October, 2004 2:34 pm, Richard Bradley said:
> Hi,
>
> I want to run stream based commands like `sed` and `tr` on the contents
> of a file, and save the results to the same file.
>
> Obviously I can do this with a temporary file:
>
> $sed s/dog/cat/ myanimals.txt > tmp.txt
> $mv tmp.txt myanimals.txt
>
> But is there any way I can do this with a single command?
>
> My first guess would be a "buffer" command that reads a file into memory
> (or into a temp file) then pipes it to stdout, e.g.
>
> $cat myanimals.txt | buffer | sed s/dog/cat/ > myanimals.txt
>
> But there isn't one which, in my experience of BSD, means it either
> wouldn't work or there is a better way to do it :-)
>
> Having read through the Bash manual and run some experiments, it seems
> that the ">" operator truncates an output file to zero length before any
> commands are run.
>
> So my missing command becomes:
>
> $cat myanimals.txt | sed s/dog/cat | bufferedwrite myanimals.txt
>
> I can't find anything like this anywhere -- any ideas what the "proper"
> way to do this is?
>
> Thanks in advance,
One way to do it, which is detailed in the O'Reilly sed & awk book[1], is
to write a thin wrapper. It needs to do the edit, save it to a temp file,
and then copy the temp file over the original.
Here is the script printed in the book (available by public ftp from
ftp.oreilly.com/published/oreilly/nutshell/sedawk_2/progs.tar.gz)
--------[ script start ]--------
#! /bin/sh
for x
do
echo "editing $x: \c"
if test "$x" = sedscr; then
echo "not editing sedscript!"
elif test -s $x; then
sed -f sedscr $x > /tmp/$x$$
if test -s /tmp/$x$$
then
if cmp -s $x /tmp/$x$$
then
echo "file not changed: \c"
else
mv $x $x.bak # save original, just in case
cp /tmp/$x$$ $x
fi
echo "done"
else
echo "Sed produced an empty file\c"
echo " - check your sedscript."
fi
rm -f /tmp/$x$$
else
echo "original file is empty."
fi
done
echo "all done"
--------[ script end ]--------
To use it, put your sed commands in a file called sedscr in the directory
containing the files to edit. Then run the command, passing it the names
of the files you want it to edit on the command line.
HTH
Dan
[1] sed & awk, 2nd edition; Dale Dougherty and Arnold Robbins; O'Reilly &
Associates, 1997.
--
Daniel Bye
PGP Key: ftp://ftp.slightlystrange.org/pgpkey/dan.asc
PGP Key fingerprint: 3B9D 8BBB EB03 BA83 5DB4 3B88 86FC F03A 90A1 BE8F
_
ASCII ribbon campaign ( )
- against HTML, vCards and X
- proprietary attachments in e-mail / \
help
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?55671.192.168.0.1.1098108251.squirrel>
