Lauras has asked for the wisdom of the Perl Monks concerning the following question:

Hi, As part of a project we have to make a portable wrapper for Clover. (http://cagt.bu.edu/page/Clover_about)

I tried to run the system function (in windows XP) from a perl script.

The program I tried to run (Clover) has a syntax as follows: clover.exe [options] mymotifs myseq.fa [backgroundfiles]

You can add more or less 10 background files. I only want to add 1 background file and redirect the output to a different file via the redirection sign ('>'). But: System LIST passes everything in the list as an argument (=background files) and does not recognise the > sign. consequently it tries to open > out.txt as if it were a background file.

remark: when I type the exact same syntax in the command line it does recognise the > sign.

can anyone help me to redirect the output?

thanx

Replies are listed 'Best First'.
Re: System call doesn't recognise '>'
by Bloodnok (Vicar) on Dec 10, 2008 at 12:50 UTC
    You don't show your code, but I'm guessing you're using the system LIST form - you could try catenating the arguments into a single string and passing that to system e.g. instead of system $arg1, $arg2, $arg3;, try either system $arg1 . $arg2 . $arg3;, or system "$arg1 $arg2 $arg3";.

    A user level that continues to overstate my experience :-))
      Indeed, I used 'system LIST'
      I already tried to add all arguments as one, and even tried to add as an array:
      @array = ($command, "$arg1 $arg2 > outfile")
      system(@array)
      Or also:
      @array=($command, $arg1, $arg2, "> outfile")
      Or also:
      @array=("$command $arg1 $arg2 > outfile")
      In the last case it didn't even recognise $command, and in the previous cases it tried to open '>' as a possible argument (=backgroundfile)
        What happens if you make the call read: system("$command $arg1 $arg2 > outfile") ?

        Note that, on Windoze, the arguments for system are the same as for exec. However, exec isn't, or wasn't, fully supported on Windoze, I think you might have to use the single string form of the call, so in your case, something along the lines of...

        my @array = qq/$command $arg1 $arg2 > outfile/; system "@array"; # Use perl to stringify the command argument list
        Just a thought...

        A user level that continues to overstate my experience :-))
Re: System call doesn't recognise '>'
by ikegami (Patriarch) on Dec 10, 2008 at 17:09 UTC
    system LIST doesn't use the shell. > is a shell command. If you wanted to use execute a shell command using system, you'd have to do
    system('sh', '-c', 'foo > file');

    or the equialent

    system('foo > file');

    The latter is also suitable for Windows.

      my @array = ($command, $arg1, $arg2, $arg3); system ('@array > $outfile');

      Results in:

      Can't spawn "cmd.exe": No such file or directory at D:\advanced_programming\test_syscall.pl line 11.

        system ('@array > $outfile');

        That line doesn't do what you think it does. Single quotes don't interpolate. You want to use double quotes and you want to check the return code of system():

        system( "@array > $outfile" ) == 0 or die "Couldn't launch [@array > $outfile]: $!/$?";
        I'd be surprised if there was a file named @array...
Re: System call doesn't recognise '>'
by almut (Canon) on Dec 10, 2008 at 16:48 UTC

    Does it work if you specify the absolute path to the shell (e.g. via COMSPEC)?  I.e.

    system "$ENV{COMSPEC} /C $command $arg1 $arg2 $arg3 > $outfile";

     

    Update: Presumably, the directory in which cmd.exe resides (typically C:\WINDOWS\system32) isn't on your PATH.

    In case of doubt, you might want to print out those variables' content:

    set path set comspec

    (COMSPEC is not guaranteed to hold the correct path to your command shell — after all, it's just an environment variable. By default, it should, however. At least, it's worth a try. (Perl doesn't use COMSPEC for this very reason of being unreliable.)   In case it doesn't hold the correct path, you could also try directly specifying system = "c:\\windows\\system32\\cmd.exe /c ...", after having verified that it in fact exists...)

    Update2: Then again, it might also be some variation of this weird issue... (not sure though).

      Comspec contained the path to cmd.exe

      But the snippet of code you included didn't work.

      cmd.exe was indeed not part of the PATH.

      I tried:

      use Env qw(@PATH); #print "@PATH\n"; unshift @PATH, "C:\\windows\\system32\\cmd.exe"; #print @PATH; system "C:\\windows\\system32\\cmd.exe /C @array > $outfile"; shift @PATH;

      The path to the command shell was added, but the result was still:

      Can't spawn "cmd.exe": No such file or directory at D:\advanced_programming\test_syscall.pl line 26.

      Or isn't it that what you suggested?

        unshift @PATH, "C:\\windows\\system32\\cmd.exe";

        That's not how the PATH environment variable works, neither in Windows nor in Unix. The PATH environment variable contains directories not executable files. Try

        unshift @PATH, "C:\\windows\\system32";

        instead, and consider not running a weirdly configured environment. Many Windows programs will fail if %WINDIR%\system32 is not in the path.

        Something else to try:  Perl (Windows only) provides for this rarely used facility to set a custom command shell via the environment variable PERL5SHELL. In other words, on the command line that you're going to call your Perl program from, set that variable (prior to calling the program):

        set PERL5SHELL=c:\\windows\\system32\\cmd.exe /c

        (yes, with doubled backslashes)

        And maybe try something trivial first, e.g.

        #!perl system "echo foo >dummy";

        In theory, you should then find a file "dummy" with the content "foo".  In case that works, try your real command...