Inplace-Edit #3

Can't do inplace edit on foo.txt: Permission denied at test.pl line 5.

などと言われてfoo.txtが空っぽになってしまいました・・・(;´Д`)ウウッ…こういう挙動はWindowsならではという感じがするけど。。。

へ?と思って Windows + Perl (Cygwin) でやってみると、うわ確かに。こっちでは空っぽというより、ファイルそのものが無くなりましたが。
ちなみに ActivePerl だとこうなる。

Can't do inplace edit without backup at test.pl line 11.

多分あれだ。システムコールの rename の挙動の違いなんだろうな。きむらさんのところから引用。

DOS/Winwdows では、すでに存在するファイルの名前に rename を実行することは できません。一方UNIXはそうではありません。 cygwinは多分その辺の動作もエミュレートしているのだと思います。 Perlはちょっと違うような? 正月早々Perlのソースに潜りたくはないので真相は各々方で一つよろしく。

ふむ。ということで、CygwinPerl がこけているところを見ると Cygwin の rename は何もエミュレートせずにツール側で対応しているのか、Perl が特殊なリンケージなのか。良く分からん。
あ、ちなみにバックアップファイルの suffix を指定してやるとちゃんと動く(バックアップファイルと同一名のファイルが既に存在してもちゃんと動く)ので、とりあえずこんな感じでごまかすという方法も。

my $filelist = ['foo.txt'];
sub main {
    local $^I = ".bak";
    local @ARGV = @$filelist;
    while (<>) {
        s/foo/bar/;
        print;
    }

    unlink map { $_ . $^I } @$filelist;
}

main;

おまけ

xargsは環境によっては無い場合があるので、ちょっと|ι´Д`|っ < むりぽ

xargs like なツールを Perl で書くというソリューションも。