views:

329

answers:

3

I am having this strange issue with Perl. I am trying to execute an external program from inside my Perl script and this external program takes string + wildcard as parameters. My Perl program looks like this

my $cmd_to_run = 'find-something-in-somedb myname* |' 
open(procHandle, $cmd_to_run); # I am using open because I want to 
                               # parse the output using pipes

For some weird reason, running this Perl script (under Windows) call to open function ends up with error:

'sqlselect' is not recognized as an internal or external command

I guessed that its something to do with * present in my command string and hence I removed it and now my command string looks like this

my $cmd_to_run = 'find-something-in-somedb myname|'

Now when I run my Perl script it works perfectly fine. Problem comes only when wildcard character is present.

Some points to note :

  1. I ran the same command with wildcard char, in the same cmd prompt (where i am executing this perl script) and it works perfectly fine..

  2. Same command works when I program it in C using _open function in Windows.

  3. Problem seems to be only when wildcard * is present , at least that's what I am guessing

  4. No, I haven't tried this in Unix..

Any clues???

EDIT : I found that this is something to do with ENV . The program that i am trying to run uses "sqlselect" only when "*" wild card is present in search string... Both find-something-in-somedb and sqlselect are present in same location. In which case how perl is able to find "find-in-db" and not "sqlselect"

Sorry i realize that original problem is turning out to be something else now.. Something to do with "ENV" and not with Wildcard *

A: 

What happens if you use three-argument open?

open my $procHandle, '-|', 'find-something-in-somedb myname*'
    or die "Cannot open pipe: $!";
Sinan Ünür
Another puzzling downvote. Hmmm ...
Sinan Ünür
I'll upvote to balance it out, but indeed... downvote and no comment explaining why?
ephemient
@Sinan - I had a puzzling downvote with no comment too.
James Thompson
@ephemient Thank you very much. I understand if my answer is ignored because it is a subset of yours but I was a little surprised to see it actively downvoted (just as I was thinking I should delete it ;-) @James Thompson I think we agree that it is common courtesy to at least tell the person who is trying to help what he is doing wrong. Thank you.
Sinan Ünür
+6  A: 

It is recommended to use the 3-argument form of open

open(procHandle, '-|', 'find-something-in-somedb', 'myname*');

as that bypasses the shell (which will perform * expansion).

However, on Windows, applications often perform their own quote-parsing and * expansion, so you may need

open(procHandle, '-|', 'find-something-in-somedb', '"myname*"');

or even

open(procHandle, '-|', 'find-something-in-somedb "myname*"');

as I'm not sure exactly how and when Perl hands things off to cmd.

ephemient
This is something to do with $PATH i guess.. Perl is able to find "find-in-db" but not "sqlselect" when both these are present in same network directory. and this network directory is added to my path variable in my cmd prompt session.
FatDaemon
Figured out that it was stupid case sensitive issue. Damn i can't be more dumb.. The problem is sqlselect is present in same directory but its file name is "SqlSelect" and perl doesn't seem to like this.
FatDaemon
That is very odd, because on Windows, looking for a file named "`sqlselect`" *should* match a file named "`SqlSelect`"... but all's good if you managed to resolve the issue. I still recommend moving to the 3-arg open: it's a good habit in general.
ephemient
+3  A: 

It's very likely that Perl is expanding the wildcard itself, which you don't want to do. The answer provided by ephemient is very good, but in order to debug this, try calling this really simple program:

print join ' ', @ARGV;

Put that into its own file, then call it from your original program (I named mine argv.pl):

my $cmd_to_run = './argv.pl myname* |' 
open(procHandle, $cmd_to_run);

That will definitively tell you on your platform how Perl is parsing things. On Unix, the * is expanded to match the files in the current working directory. Not sure about Windows though.

James Thompson