help for exec with command lines with spaces

P

PilotMI80

Hi,

I try to issue the command :
c:\program files\flashget\flashget.exe http:\\url.with.no.white.space
d:\a directory

(same can be tested with any prog that need a directory (potentially
containing whitespaces) as a parameter )

the url parameter does not contain whitespace so it is not a matter


so far, I tried many combinations (to escape baskslashes and quotes)
with the back tick (seems to work better for me although i don't need
the output), and with exec but to no avail :

here are a few :
1.
exec "c:\\program files\\flashget\\flashget.exe url d:\\a directory";
output> 'c:\program' not found (expected)

2.
exec "\"c:\\program files\\flashget\\flashget.exe\" url";
works ok but
exec "\"c:\\program files\\flashget\\flashget.exe\" \"url\"";
outputs 'c:\program' not found

3.
my @exe = ("\"c:\\program files\\flashget\\flashget.exe\" url \"d:\a
directory\"");
exec {$exe[0] } @exe; #as read in the manual
outputs nothing but does nothing because the command issue is wrong
(I assume the program is not the whole line so...)

4.
my @exe = ("\"c:\\program files\\flashget\\flashget.exe\"");
exec {$exe[0]} @exe, url; # or "url" or 'url' or " url" or ' url' ...
compiles but does nothing

I run out of ideas and am still stuck, by now, i do something like
this :
`"\"c:\\program files\\flashget\\flashget.exe\" url d:\\a_directory\"
which works but is quite limited.

any suggestion ?

thanks
 
P

PilotMI80

Finally I managed to do what I wished :
my $ProgramExe = "\"C:\\The path to the\\executable.exe\"";
my $OneArgument = "OneArgumentThatDoesNotContainSpace";
my $SecondArgument = "\"D:\\Another Argt\\that contains spaces\"";

system("start \"\"", $ProgramExe, $OneArgument, $SecondArgument);

Some explanations for the ones who may encounter this concern (and
feel free to correct me if I am wrong or not precise enough) :
- system behaves differently whether it is passed a scalar argument or
a list. I will not repeat the FAQ but it is often useful to force LIST
context to avoid misinterpretation by the shell. (So we meet the form
exec {"FakeName"} @ForcedToBeListCommandLine)

- I use "start" because I'm running on Win32, so it let the system
launch a program as if it was launched from the start menu/Run.
Otherwise, the script waits for the command to end (exec does not work
neither cause it just turns the script process to the one just
launched and there is no point of return)

- \"\" is the FakeName, the name we invoked the program under. (In
this case I don't need to pretend my program was launched under a
particular name so I let it blank)

- $ProgramExe and $SecondArgument were quoted in order to have the
white spaces preserved on the command line issued;
- $OneArgument does not contain any white space so I let it unquoted

- I kept my different arguments in a LIST (and thus separated) not to
have to rebuild my command line for any argument I want to issue but
they could have been grouped together into one argument.

Hope it will help someone
 
B

Ben Morrow

Quoth (e-mail address removed) (PilotMI80):
I try to issue the command :
c:\program files\flashget\flashget.exe http:\\url.with.no.white.space ^^ //
d:\a directory

(same can be tested with any prog that need a directory (potentially
containing whitespaces) as a parameter )

Either use list exec wih the correct (unescaped) path:

my @args = (
'c:/program files/flashget/flashget.exe',
'http://stuff',
'd:\\a directory',
);
exec @args;

(btw, you have read perldoc -f exec, haven't you?), or quote it
correectly for your shell (IIRC this should work for cmd.exe):

exec map s/\s*\n\s*/ /g, q{
"c:\\program files\\flashget\\flashget.exe
http://stuff
"d:\\a directory"
};

I am here assuming that flashget.exe requires paths to be \-separated:
IME, most windows programs do, even though windows itself (and therefore
perl) are quite happy with / paths.

Ben
 
B

Ben Morrow

Quoth (e-mail address removed) (PilotMI80):
Finally I managed to do what I wished :
my $ProgramExe = "\"C:\\The path to the\\executable.exe\"";
my $OneArgument = "OneArgumentThatDoesNotContainSpace";
my $SecondArgument = "\"D:\\Another Argt\\that contains spaces\"";

system("start \"\"", $ProgramExe, $OneArgument, $SecondArgument);

You don't need any of this mess. Perl on Win32 knows how to quote
arguments correctly for the standard command-line parsing routines:

my $ProgramExe = 'C:\\The path to the\\executable.exe';
my $OneArgument = 'OneArgument';
my $SecondArgument = 'D:\\Another argt';

system 'start', $ProgramExe, $OneArgument, $SecondArgument;
Some explanations for the ones who may encounter this concern (and
feel free to correct me if I am wrong or not precise enough) :
- system behaves differently whether it is passed a scalar argument or
a list. I will not repeat the FAQ but it is often useful to force LIST
context to avoid misinterpretation by the shell. (So we meet the form
exec {"FakeName"} @ForcedToBeListCommandLine)

Perl will not call the shell for a one-arg system or exec unless the arg
contains shell metachars.

You have got the indirect object and the first arg the wrong way round:
the indirect object is what is actually being executed. In any case,
they should be the same (unless you need them different), so to run a
command with no args but with spaces in the name use

my $cmd = '/path to/command';
system {$cmd} $cmd;
- I use "start" because I'm running on Win32, so it let the system
launch a program as if it was launched from the start menu/Run.
Otherwise, the script waits for the command to end (exec does not work
neither cause it just turns the script process to the one just
launched and there is no point of return)

Yup. You could also use Win32::process, if you wanted more control over
your 'child'.
- \"\" is the FakeName, the name we invoked the program under. (In
this case I don't need to pretend my program was launched under a
particular name so I let it blank)

No. I am actually rather surprised this worked at all...

You have *not* used the indirect object syntax here. Those ""
are inside the first arg, so what you are asking Perl to do is execute a
program called (literally)

start "".exe

(or some other executable extension). The fact that the windows
doesn't use the C arg-passing convention means that it worked out what
you meant anyway...
- $ProgramExe and $SecondArgument were quoted in order to have the
white spaces preserved on the command line issued;

Nope. Perl will deal with this for you if you use system LIST.
- I kept my different arguments in a LIST (and thus separated) not to
have to rebuild my command line for any argument I want to issue but
they could have been grouped together into one argument.

Nope. system LIST is quite different from system SCALAR, as you said to
start with.

Ben
 

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

Similar Threads


Members online

No members online now.

Forum statistics

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

Latest Threads

Top