On Thu, 28 Mar 2002 12:17:28 +0800, allan wrote:
>hello
>
>i need to detab a bunch of files in a bunch of directories.
>
>this script:
>
>#!/usr/bin/perl -pi
>s/\t/ /;
>
>
>will do what i want when a supply the files as arguments
>from the commandline.
Wow, hold it. If you use something that simple, you'll likely end up
with some weird looking text (source?) files.
You seem to want tab positions every 4 columns. Now, somebody will
likely suggest using some module for that, but here is some handcrafted
code:
s/(.*?)\t/$1.(' ' x (4-length($1)%4))/ge;
It will take into account the length of the string before the tab
starting from the start of the string, from the previous newline, or
from the last replaced tab; and pad with 1 to 4 spaces so the string
length becomes the next multiple of 4.
It seems to work fine for me.
>i have a script that traverse all directories from a
>specfied starting point.
>so when i recursively get to a new file i wish to detab that
>file on the fly as if i had supplied the filename as an argument
>
>sub recursion {
> ...
> if (-f $specfile ) {
> # detab code goes here
> }
> ...
> # next file/dir
>}
>
>
>is that possible still using the -i switch?
My first thought would be to have two scripts, and call the other script
with
system($^X, "-pi", "detab.pl", $_);
$^X is the full path of the perl executable.
But, then, of course, your platform should support calling external perl
scripts this way. I think that this will be problematic on a Mac, most
of all if you don't have ToolServer installed (IIRC).
Also note that some platforms do require that you provide an extension
for the -i command line switch. (Windows, Mac ?) You'll get a backup
file that way, I know...
BTW instead of calling an external script, you ougth to be able to use
the -e command line option.
A second approach would be to have just one script, fill @ARGV in a
BEGIN block. Yeah, that looks like it would be the best approach.
#!/usr/bin/perl -pi
BEGIN {
use File::Find;
use Cwd;
my @argv = @ARGV; @ARGV = ();
find sub {
push @ARGV, $File::Find::name if -f and /\.txt$/;
}, @argv ? @argv : cwd;
}
s/(.*?)\t/$1.(' ' x (4-length($1)%4))/ge;
UNTESTED!
The idea is that you pass the path of the root directory(/-ies) on the
command line, or it will pick the current working directory without
arguments. It will fill @ARGV with a complete list of all found files.
BTW any plain files in the command arguments get included too, if they
match the pattern. That's a feature of File::Find.
It does that in a BEGIN block, so this is run once, at the start of your
script. The main body of the script is run using the -pi command line
switches, so that part runs once for every line in the input files.
HTH,
Bart.