globbing files with spaces in the path

S

Scott Bass

Active State Perl 5.8.6 under Windows

Hi,

Here is an excerpt from a Perl script I wrote:

test.pl:

#!perl

# set pragmas
use strict;
use warnings;

# include desired modules
use Getopt::Long;
use File::Basename;

# glob files specified on the command line
my @files;
while (@ARGV) {
push @files, glob(shift @ARGV);
}

# process each file
my ($dirname, $basename);
while (@files) {
$_ = shift @files;
$basename = basename($_);
$dirname = dirname($_);

print $dirname,"\n";
print $basename,"\n";
}

__END__

Say test.pl is in my path. If in a command window I do:

cd C:\A Path\With Spaces\In It
test.pl *.txt

it works as expected.

However, if I do:

cd c:\
test.pl "C:\A Path\With Spaces\In It\*.txt"

it fails.

How can I change the above script so it will work in both scenarios?

Regards,
Scott
 
R

robic0

Active State Perl 5.8.6 under Windows

Hi,

Here is an excerpt from a Perl script I wrote:

test.pl:

#!perl

# set pragmas
use strict;
use warnings;

# include desired modules
use Getopt::Long;
use File::Basename;

# glob files specified on the command line
my @files;
while (@ARGV) {
push @files, glob(shift @ARGV);
}

# process each file
my ($dirname, $basename);
while (@files) {
$_ = shift @files;
$basename = basename($_);
$dirname = dirname($_);

print $dirname,"\n";
print $basename,"\n";
}

__END__

Say test.pl is in my path. If in a command window I do:

cd C:\A Path\With Spaces\In It
test.pl *.txt

it works as expected.

However, if I do:

cd c:\
test.pl "C:\A Path\With Spaces\In It\*.txt"

it fails.

How can I change the above script so it will work in both scenarios?

Regards,
Scott
Your subject belies your content.
Have you "glob"'ed today?
Some of your program constructs truly suck. I'ts hard to cut and past
with ratioanal. I suggest you strip out all the code that has to do with
you truly crappy program, and paste the 2 or 3 lines of test code that
has to do with you "glob" subject.
-robic-
 
G

Gunnar Hjalmarsson

Scott said:
Active State Perl 5.8.6 under Windows

# glob files specified on the command line
my @files;
while (@ARGV) {
push @files, glob(shift @ARGV);
}

If in a command window I do:

cd C:\A Path\With Spaces\In It
test.pl *.txt

it works as expected.

However, if I do:

cd c:\
test.pl "C:\A Path\With Spaces\In It\*.txt"

it fails.

How can I change the above script so it will work in both scenarios?

Without changing the script, you can do:

cd c:\
test.pl "C:\APATH~1\WITHSP~1\INIT~1\*.txt"

Besides that, it's my experience that you achieve more robust and
portable code with opendir() and readdir() than you do with glob().
 
T

Tad McClellan

I'ts hard to cut and past
with ratioanal.
^^^^^^^^^
^^^^^^^^^ ?


Is that when someone is only fractionally an asshole?


(if so, then it wouldn't be applying to you, so what's the problem?)
 
H

Henry Law

robic0 said:
Some of your program constructs truly suck. I'ts hard to cut and past
with ratioanal. I suggest

Scott, this robic fellow is really unpleasant. Don't take any notice of
him.

Have you tried debugging this with "perl -d"? Look:
F:\WIP>perl -d testng.pl "C:\wip\a b\*.txt"
main::(testng.pl:12): my @files;
DB<1> n
main::(testng.pl:13): while (@ARGV) {
DB<1> x @ARGV
0 'C:\\wip\\a b\\*.txt'
DB<2> n
main::(testng.pl:14): push @files, glob(shift @ARGV);
DB<2> n
main::(testng.pl:18): my ($dirname, $basename);
DB<2> x @files
0 'C:./wipa'

If I were you I'd not mess about trying to work out why glob is doing
what it is. Personally I've found glob to be a bit unpredictable from
time to time and generally prefer readdir or maybe File::Find. Or
maybe separate out the path and the filespec from @ARGV and change to
the directory separately from globbing the filespec.
 
S

Scott Bass

Henry Law said:
Scott, this robic fellow is really unpleasant. Don't take any notice of
him.

Have you tried debugging this with "perl -d"? Look:



If I were you I'd not mess about trying to work out why glob is doing what
it is. Personally I've found glob to be a bit unpredictable from time to
time and generally prefer readdir or maybe File::Find. Or maybe separate
out the path and the filespec from @ARGV and change to the directory
separately from globbing the filespec.

Hi Henry,

Thanks for the positive comment re: robic. I pretty much expect to be
abused by someone whenever I post to c.l.p.m. Unfortunately I don't work
with Perl enough to get as good as I would like (love the language though).
I do my best to read my O'Reilly books and check the doc before I post.

Your and other's comments about glob unpredictability triggered an idea
about where to look in the doc. This seems to have fixed the issue:

use File::Glob ':glob';

# glob files specified on the command line
my @files;
while (@ARGV) {
push @files, bsd_glob(shift @ARGV);
}

It's important that the end user be able to specify something like this on
the command line:

test.pl "C:\A Path\*.foo" C:\Path\*.bar "C:\Another Path\*.blah"

and all the files get processed.

Lastly, I want to configure this script as a custom action in Windows
Explorer (say I call it "Batch Submit"), such that RMB --> "Batch Submit"
executes the script against the file in question. In that scenario, %1 is
the full path of the file that was RMB'd, so Gunnar's idea of
"C:\APATH~1\WITHSP~1\INIT~1\*.txt" wouldn't work. (I'll have to use pl2bat
to convert the script to a .bat file).

If I can do the above (process command line wildcards) using opendir and
readdir, could someone post a code snippet?

Thanks again,
Scott
 
H

Henry Law

Scott said:
Lastly, I want to configure this script as a custom action in Windows
Explorer (say I call it "Batch Submit"), such that RMB --> "Batch Submit"

I'm looking forward to someone showing me what I missed (well, sort of
...) but my experience of these context menu actions is that you have to
code them as perlSCRIPT, which is different from Perl. For example
@ARGV doesn't work - it's empty as I remember - and you have to code
my $args = $WScript->Arguments;

.... and then process $args->Arguments as an array. I couldn't find a
way of running Perl debug on these perlscripts either; had to code
dozens of $WScript->Echo("Such-and-such is happening") lines and dismiss
dozens of message boxes.

It's been a while since I tangled with it.
 
G

Gunnar Hjalmarsson

Scott said:
This seems to have fixed the issue:

use File::Glob ':glob';

# glob files specified on the command line
my @files;
while (@ARGV) {
push @files, bsd_glob(shift @ARGV);
}

If I can do the above (process command line wildcards) using opendir and
readdir, could someone post a code snippet?

Well, when mentioning those functions, I had another idea about how to
feed the input to the script. But maybe something like this:

my @files;
while (@ARGV) {
push @files, myglob(shift @ARGV);
}

sub myglob {
my $arg = shift;
my ($dir, $ext);
if ( $arg =~ /^(c:.*)\\\*\.(\w+)$/i ) {
($dir, $ext) = ($1, $2);
} else {
die "Unexpected argument: $arg\n";
}
opendir my $dh, $dir or die "Couldn't open $dir: $!\n";
map { "$dir\\$_" } grep /\.$ext$/, readdir $dh;
}
 
S

Scott Bass

Henry Law said:
I'm looking forward to someone showing me what I missed (well, sort of ..)
but my experience of these context menu actions is that you have to code
them as perlSCRIPT, which is different from Perl. For example @ARGV
doesn't work - it's empty as I remember - and you have to code


... and then process $args->Arguments as an array. I couldn't find a way
of running Perl debug on these perlscripts either; had to code dozens of
$WScript->Echo("Such-and-such is happening") lines and dismiss dozens of
message boxes.

It's been a while since I tangled with it.

Hi Henry,

I created this script as a POC (using pl2bat; Windows Explorer does not
accept a .pl file as a valid action):

@rem = '--*-Perl-*--
@echo off
if "%OS%" == "Windows_NT" goto WinNT
perl -x -S "%0" %1 %2 %3 %4 %5 %6 %7 %8 %9
goto endofperl
:WinNT
perl -x -S %0 %*
if NOT "%COMSPEC%" == "%SystemRoot%\system32\cmd.exe" goto endofperl
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 endofperl
@rem ';
#!perl

# set pragmas
use strict;
use warnings;

# include desired modules
use Getopt::Long;
use File::Basename;
use File::Glob ':glob';

# glob files specified on the command line
my @files;
while (@ARGV) {
push @files, bsd_glob(shift @ARGV);
}

# process each file
my ($dirname, $basename);
while (@files) {
$_ = shift @files;
$basename = basename($_);
$dirname = dirname($_);

chdir($dirname);
open(FH,$basename);
while(<FH>) {
print;
}
close(FH);
}

__END__
:endofperl

pause;

In Windows Explorer, for the file type in question, I created this new
action:

"C:\Documents and Settings\Scott Bass\My Documents\My Perl
Scripts\test8.bat" "%1"

When I RMB on the file in question and select this action, the contents of
the file are printed to the cmd window. So I would think this would work
fine with my final application.

This under Windows XP.

Regards,
Scott
 
H

Henry Law

I created this script as a POC (using pl2bat; Windows Explorer does not
accept a .pl file as a valid action):

@rem = '--*-Perl-*--
@echo off
if "%OS%" == "Windows_NT" goto WinNT
perl -x -S "%0" %1 %2 %3 %4 %5 %6 %7 %8 %9
goto endofperl
:WinNT
perl -x -S %0 %*
if NOT "%COMSPEC%" == "%SystemRoot%\system32\cmd.exe" goto endofperl
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 endofperl
@rem ';
#!perl

# set pragmas
.... etc for the rest of the Perl program

Isn't it wonderful how newsgroups work. I joined in here to try to help
you out, and end up learning from you something I had overlooked -
pl2bat and this "perl -x" stuff. Thanks! Now I can go re-write my
perlscript thing in a much more elegant manner.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,577
Members
45,054
Latest member
LucyCarper

Latest Threads

Top