Using the same file as stdin and stdout results in empty file

2

If want to filter a file but if I use the same file as input and output the output file is empty. Is there another solution instead of using a second file?

php -r "echo preg_replace('~/\* DEV \*/(.*)/\* ENDDEV \*/~si', '', file_get_contents('php://stdin'));" < build/index.php > build/index.php

Bob

Posted 2013-09-16T10:18:49.897

Reputation: 23

use the file as a basis, then create a new one, delete the original and rename the new one is not an option i assume. this could also be useful as a backup basis, since you're editing a sensitive file (an index) – Lorenzo Von Matterhorn – 2013-09-16T10:22:48.353

Its definetly an option but there has to be another, cleaner way. – Bob – 2013-09-16T10:23:53.597

2I'm fairly sure that there actually isn't a cleaner way, since even programs with an 'edit in place' option, like sed, actually create temporary files and then overwrite. – evilsoup – 2013-09-16T10:32:13.690

Answers

6

When you open a file for writing with >, it is truncated before you even read it. That's why it's empty.

Alternative with a temporary file (yes, this is quite common):

php -r "…" < build/index.php > tmp
mv tmp build/index.php

Ideally, use mktemp to generate a unique temporary file:

tmp="$(mktemp /tmp/file.XXX)"
php -r "…" < build/index.php > "$tmp"
mv "$tmp" build/index.php

But this isn't really shorter or more concise.


My personal favorite is the sponge utility from moreutils – it reads input and then writes to the file:

php -r "…" < build/index.php | sponge build/index.php

Or, better yet, don't do the substitution in PHP, but a tool that supports in-place editing, like Perl with:

perl -pi -e '…' build/index.php

Similar with sed, here the in-place flag for GNU sed:

sed -i -e '…' build/index.php

And for BSD sed, you need an explicit empty argument for -i:

sed -i '' -e '…' build/index.php

You will probably have to adapt your regular expression / substitution command for Perl's and sed's syntax, respectively.

slhck

Posted 2013-09-16T10:18:49.897

Reputation: 182 472

Or sed if it has the -i option. – Bobby – 2013-09-16T14:33:33.243

Should probably use mktemp for the temporary file. – Daniel Beck – 2013-09-18T19:16:41.370

@Daniel Of course – added that. The OP wanted something "clean" though, so I was hesitant to include even more code when the actual solution is just to use the proper tool, for example. – slhck – 2013-09-18T19:49:08.980