Editing files in-place with sponge
$ apt-get install moreutils $ man sponge
Editing existing files in-place with regular UNIX-tools like
awk, or — like in my case — expand
(which converts tabs to spaces), can be a hassle.
The obvious first attempt is to run it like this:
me:~/tmp$ cat > bad.py def foo(): print "I'm using tabs!" me:~/tmp$ cat bad.py | expand - | sed -e s/tabs/spaces/ > bad.py me:~/tmp$ cat bad.py me:~/tmp$
Aaaaah, it's empty!!!!11eleventyone
The reason: Since all these commands run in parallel, you're reading from the file at the same time that you're already writing to it. In the normal case, you'll get an empty file. (You lose your data!)
This is where the
sponge tool from the Debian
moreutils package comes into play:
sponge file gobbles up all input piped into it, and only after that is done, it will write the input to the given file.
me:~/tmp$ cat > bad.py def foo(): print "I'm using tabs!" me:~/tmp$ cat bad.py | expand - | sed -e s/tabs/spaces/ | sponge bad.py me:~/tmp$ cat bad.py def foo(): print "I'm using spaces!"
It works, w00t!
Now, to convert all source code in the current directory:
$ for i in *.scm; do expand "$i" | sponge "$i"; done
There's an even more elaborate writeup on these techniques at http://backreference.org/2011/01/29/in-place-editing-of-files/.