Out of curiosity, I wrote an in-place editor with the intent of robustly handling all filenames and trying to avoid shell command-line length issues. The program below takes one or more directories (defaulting to the current directory if none are specified) and creates a find ... | xargs ...
pipeline that attempts to give @ARGV
only those PHP sources that need tweaking.
#! /usr/bin/perl
use warnings;
use strict;
BEGIN {
@ARGV = (".") unless @ARGV;
my $xargspid = open my $xargs, "-|";
die "$0: fork: $!" unless defined $xargspid;
my @paths;
if ($xargspid) {
local $/ = "\0";
while (<$xargs>) {
chomp;
push @paths => $_;
}
unless (close $xargs) {
my $status = $? >> 8;
die "$0: xargs exited $status"
if $status != 0 && $status != 123;
}
}
else {
my $findpid = open my $find, "-|";
die "$0: fork: $!" unless defined $findpid;
if ($findpid) {
open STDIN, "<&", $find or die "$0: dup find: $!";
exec "xargs", "--null", "egrep", "-lZ", 'include[[:space:]]*\('
or die "$0: exec xargs: $!";
}
else {
exec "find", @ARGV, "-maxdepth", 1,
"-name", "*.php",
"-print0"
or die "$0: exec find: $!";
}
}
@ARGV = @paths;
}
At this point, @ARGV
may be empty, and if so we bail.
unless (@ARGV) {
warn "$0: nothing to do\n";
exit 1;
}
Otherwise, we mimic the processing of the -i
switch, which must go through <>
and print
. The code at least warns about errors such as the filesystem running out of space rather than failing silently.
# $^I = ""; # no backup
$^I = ".bak";
while (<>) {
s/include\s*\(/include_once(/g;
print;
}
continue {
if (eof) {
close ARGV or warn "$0: close $ARGV: $!\n";
}
}
Sample run:
$ ./fixinc
$ ls *.php
bar.php baz.php foo.php
$ ls *.bak
bar.php.bak foo.php.bak
$ diff -ub foo.php.bak foo.php
--- foo.php.bak
+++ foo.php
@@ -1 +1 @@
-include(foo)
+include_once(foo)
$ diff -ub bar.php.bak bar.php
--- bar.php.bak
+++ bar.php
@@ -1 +1 @@
-include (bar)
+include_once(bar)