How to run a stream based command in place on a file

Daniel Bye freebsd at slightlystrange.org
Mon Oct 18 07:04:14 PDT 2004


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 / \



More information about the freebsd-questions mailing list