Editing files in-place with sponge
TL;DR:
$ apt-get install moreutils $ man sponge
Editing existing files in-place with regular UNIX-tools like
sed
, awk
, or — like in my case — expand
(which converts tabs to spaces), can be a hassle.
A Non-solution
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!)
Teh solution
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/.