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>
next in thread | previous in thread | raw e-mail | index | archive | help
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 / \
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?55671.192.168.0.1.1098108251.squirrel>