Modify files in place with shell commands

Available on Github

A shell pipeline cannot both read and write to the same file; for example

cat foo | grep bar > foo

will merely delete the contents of foo.

A clumsy (and in some cases, slow or unworkable) workaround is to pipe the output to a temporary file, then move that file over the original. This requires free disk space equivalent to the size of the new file, however.

Insitu wraps a shell command, connecting its standard input and standard output to the given file. If command finishes successfully, file will be truncated (or extended) to the size of the output produced by command. If command returns a non-zero exit status, file will not be truncated (unless -t is passed), but contain the output read from the command, followed by the rest of the original contents of file. The part of file overwritten by the command output will be lost.

With insitu, the above would be written as

insitu foo 'grep bar'

Another handy use is to prepend something to an existing file:

insitu foo 'echo whatever; cat'

Insitu runs the command with $SHELL -c command, substituting /bin/sh for $SHELL if the latter is not set.