Welcome to the world of software development! "It worked fine for years on
XYZ.." is
something I've heard so often with software that contains hidden bugs that were
never found,
often because of poor initial design. :-(
"perl -w" and "use warnings;" are your friends!
Here was my first run, with the code just copy/pasted from your mail message:
D:\test>perl-test
1 file(s) copied.
1 file(s) copied.
1 file(s) copied.
1 file(s) copied.
1 file(s) copied.
1 file(s) copied.
1 file(s) copied.
syntax error at test-script.bat line 24, near ";,"
Execution of test-script.bat aborted due to compilation errors.
D:\test>
The problem appears to be that you have a spurious comma:
my $DIR;,
if ( -d $top ) { ... }
Perl sees this as
( (/*NULL EXPRESSION*/) , (/*IF STATEMENT*/) );
which of course, evaluates the left and right parts of the comma operator, and
uses the left-
side value as the value of the entire expression.. So it evaluates to a null
expression. And
Perl is quite happy to do nothing!
Here's the fixed scripts (note that I also did some other cleanup, but it's
still far from what I'd
call a "production" script!).. It works just fine now, as show further below:
FILE perl-test.bat:
========================================
@echo off
rem ********************
rem Make the directories
rem ********************
if not exist "some dir with spaces" (
mkdir "some dir with spaces"
)
if not exist "some dir with spaces\some subdir with spaces" (
mkdir "some dir with spaces\some subdir with spaces"
)
if not exist "some dir with spaces\some subdir with spaces\even deeper" (
mkdir "some dir with spaces\some subdir with spaces\even deeper"
)
if not exist "some other dir with spaces" (
mkdir "some other dir with spaces"
)
if not exist "some other dir with spaces\monotonous, isn't this" (
mkdir "some other dir with spaces\monotonous, isn't this"
)
if not exist "nospaces" (
mkdir "nospaces"
)
if not exist "nospaces\done!" (
mkdir "nospaces\done!"
)
rem ********************
rem Make the files
rem ********************
if not exist "some filename with spaces.txt" (
copy NUL "some filename with spaces.txt"
)
if not exist "some dir with spaces\some subdir with spaces\another
file.txt" (
copy NUL "some dir with spaces\some subdir with spaces\another file.txt"
)
if not exist "some dir with spaces\some subdir with spaces\even
deeper\whee.txt" (
copy NUL "some dir with spaces\some subdir with spaces\even
deeper\whee.txt"
)
if not exist "some other dir with spaces\more spaces %%and [EMAIL
PROTECTED] $chars.txt" (
copy NUL "some other dir with spaces\more spaces %%and [EMAIL
PROTECTED] $chars.txt"
)
if not exist "some other dir with spaces\monotonous, isn't this\woot.txt" (
copy NUL "some other dir with spaces\monotonous, isn't this\woot.txt"
)
if not exist "nospaces\foo.txt" (
copy NUL "nospaces\foo.txt"
)
if not exist "nospaces\done!\bar.txt" (
copy NUL "nospaces\done!\bar.txt"
)
rem ********************
rem Test the script
rem ********************
call test-script.bat
========================================
FILE test-script.bat:
========================================
@rem = '--*-Perl-*--
@echo off
if "%OS%" == "Windows_NT" goto WinNT
set ORIGPATH9X=%PATH%
set PATH=%PATH%;D:\Devel\Perl\Perl5\bin
perl -x -S "%0" %1 %2 %3 %4 %5 %6 %7 %8 %9
goto endofperl
:WinNT
setlocal
set PATH=%PATH%;D:\Devel\Perl\Perl5\bin
perl -x -S %0 %*
if NOT "%COMSPEC%" == "%SystemRoot%\system32\cmd.exe" goto endoffile
if %errorlevel% == 9009 echo You do not have Perl in your PATH.
if errorlevel 1 goto script_failed_so_exit_with_non_zero_val 2>nul
goto endofperlNT
@rem ';
#! /usr/bin/perl -w
#line 19
use strict;
use warnings;
use Data::Dump qw( pp );
sub dir_walk {
my ($top, $filefunc, $dirfunc) = @_;
my $DIR;
if ( -d $top ) {
my $file;
unless (opendir $DIR, $top) {
warn "Couldn't open directory $top: $!; skipping.\n";
return;
}
my @results;
while ($file = readdir $DIR) {
next
if $file eq '.' || $file eq '..';
push @results, dir_walk("$top/$file", $filefunc, $dirfunc);
}
return $dirfunc->($top, @results);
} else {
return $filefunc->($top);
}
}
sub file_func {
print "file_func:\t" . pp(@_) . "\n";
}
sub dir_func {
print "dir_func:\t" . pp(@_) . "\n";
}
sub main {
dir_walk("d:/test", \&file_func, \&dir_func);
}
main();
__END__
:endofperlNT
endlocal
goto endoffile
:endofperl9X
set PATH=%ORIGPATH9X%
set ORIGPATH9X=
:endoffile
========================================
OUTPUT (doesn't really reformat well to email, but.. you can see it works):
========================================
D:\test>perl-test
file_func: "d:/test/nospaces/done!/bar.txt"
dir_func: ("d:/test/nospaces/done!", 1)
file_func: "d:/test/nospaces/foo.txt"
dir_func: ("d:/test/nospaces", 1, 1)
file_func: "d:/test/perl-test.bat"
file_func: "d:/test/some dir with spaces/some subdir with
spaces/another file.txt"
file_func: "d:/test/some dir with spaces/some subdir with spaces/even
deeper/whee.txt"
dir_func: (
"d:/test/some dir with spaces/some subdir with spaces/even deeper",
1,
)
dir_func: ("d:/test/some dir with spaces/some subdir with spaces", 1,
1)
dir_func: ("d:/test/some dir with spaces", 1)
file_func: "d:/test/some filename with spaces.txt"
file_func: "d:/test/some other dir with spaces/monotonous, isn't
this/woot.txt"
dir_func: (
"d:/test/some other dir with spaces/monotonous, isn't this",
1,
)
file_func: "d:/test/some other dir with spaces/more spaces %and [EMAIL
PROTECTED]
\$chars.txt"
dir_func: ("d:/test/some other dir with spaces", 1, 1)
file_func: "d:/test/test-script.bat"
dir_func: ("d:/test", 1, 1, 1, 1, 1, 1)
D:\test>
========================================
If your scripts still won't work after cleaning up, then check into what your
build of Perl is
doing, as I don't think it's the script itself. You might also want to look
into the File::Find Perl
module, available on CPAN, in the AS repositories, etc.
Best of luck.
Cas
On 23 Sep 2008 at 14:59, Dennis Daupert wrote:
>
> Hi List,
>
> I've worked with Perl on Unix for years, still a beginner on windows.
>
> I have a script that recursively travels down a file and directory
> tree and captures file stats. Works fine on Solaris.
>
> The script has a problem when it hits a directory or filename
> containing spaces.
>
> I'll paste the subroutine code below; I borrowed from Mark Jason
> Dominus' "Higher Order Perl"
>
> Basically, this is a recursive subroutine. You feed it some directory
> that gets populated into the variable $top (eg, C:\path\to\some dir),
> as well as feed it a couple of callbacks.
>
> The code below breaks down when it hits the test operator -d and $top
> contains a directory with a space (/some dir/). The test operator
> doesn't seem to recognize the directory-with-space as a directory, so
> the whole if condition is bypassed.
>
> I've played with such things as putting quotes around the offending
> directory, around the whole path, etc., with no joy. The best he does
> is read the toplevel directory handed to him, but then he stops. I
> need a more robust way of handling this strange filesystem.
>
> ===========================================
> Here's the code:
>
> sub dir_walk {
> my ($top, $filefunc, $dirfunc) = @_;
> my $DIR;,
>
> if ( -d $top ) { # << FAILS HERE
> my $file;
> unless (opendir $DIR, $top) {
> warn "Couldn't open directory $top: $!; skipping.\n";
> return;
> }
>
> my @results;
> while ($file = readdir $DIR) {
> next if $file eq '.' || $file eq '..';;
> push @results, dir_walk("$top/$file", $filefunc, $dirfunc);
> }
>
> return $dirfunc->($top, @results);
>
> } else {
> return $filefunc->($top);
> }
> }
> ===========================================
>
> best,
>
> /dennis
>
> ------------------------------------------------
> Dennis Daupert, PhD
> Senior Systems Development Professional -- CSC Account
> CSC
>
> GOS | o: 1.317.298.9499 | [EMAIL PROTECTED] | www.csc.com
>
> This is a PRIVATE message. If you are not the intended recipient,
> please delete without copying and kindly advise us by e-mail of the
> mistake in delivery. NOTE: Regardless of content, this e-mail shall
> not operate to bind CSC to any order or other contract unless pursuant
> to explicit written agreement or government initiative expressly
> permitting the use of e-mail for such purpose.
>
> _______________________________________________
> Perl-Win32-Users mailing list
> [email protected]
> To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs
_______________________________________________
Perl-Win32-Users mailing list
[email protected]
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs