Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid

System call in Windows

by csarid (Sexton)
on Oct 24, 2008 at 19:03 UTC ( #719410=perlquestion: print w/replies, xml ) Need Help??
csarid has asked for the wisdom of the Perl Monks concerning the following question:

I am running a perl script from "windows" which does a few things and then I want to replace a value in a file with a new value. (Note: this works find on unix but not windows).

Here is the code for the script:
system(perl -pib -e "s/CAT/mouse/g" 'D:\tmp\file.txt');

The Data file file.txt contains the line:
"The CAT in the HAT"
I've tried many combinations google, search this site, and have not seen any example that's similar.

Any help would be appreciated.


Replies are listed 'Best First'.
Re: System call in Windows
by NateTut (Deacon) on Oct 24, 2008 at 19:28 UTC
    Try: system("perl -pib -e \"s/CAT/mouse/g\" D:\\tmp\\file.txt");
      Hello NateTut,
      Thanks that worked great! Can you tell or point me to somewhere where it explains the weirdness. Thanks again!
        Hmm, I don't know of a good reference on this particular issue, maybe someone else does, it is more of an operating system issue than a perl issue though. Windoze/DOS likes double quotes and *nix prefers single. I've had that particular issue bite me in the behind enough to recognize it when I see it. I would recommend though when faced with an odd problem such as this create a little test script that duplicates the problem and then just try different things. A lot of times the errors you get doing this along with simplifying it down to it's essence is enough to figure it out on your own. You get to learn something along the way as a bonus!
        If the code in your original post is accurate, then you have several unquoted arguments, and I get a syntax error, even on Unix, so I'm surprised if it really does work. Fixing it comes down to passing system() a string, which means you have to escape each argument correctly for the shell (and deal with OS quoting), or passing system() an array, which means you don't have to escape any arguments. It's usually better to pass an array, when possible.
        Thanks that worked great! Can you tell or point me to somewhere where it explains the weirdness. Thanks again!

        I personally believe that there's no weirdness at all: system either wants a single string as an arguments list, or a several ones. In the former case, the string is parsed for shell metacharachters and if any, it is processed by the system's shell, otherwise, it is split up in "words" and executed directly by the suitable system call. The same happens in the latter case, directly. Now, your code as you posted in the root node is

        system(perl -pib -e "s/CAT/mouse/g" 'D:\tmp\file.txt');

        which would seem to fall in the second category, but most importantly contains many barewords: these should be disallowed at all if you're running under strict and you know you should run under strict except perhaps with the simplest oneliners. There should be no difference between operating systems wrt this issue. Moreover, the barewords are not separated by commas which also would make for a Perl syntax error irrespective of the OS, and strict too. All in all, you seem to think that whatever is an argument to system() doesn't need any quoting, as if perl itself were a shell, but that's not the case. You either want:

        system qq|perl -pib -e "s/CAT/mouse/g" 'D:\tmp\file.txt'|;

        (in which I used alternate delimiters on the outer string not to have to quote double quotes inside it) or

        system 'perl', '-pib', '-e', '"s/CAT/mouse/g"', q|'D:\tmp\file.txt'|;

        Incidentally, since no argument contains spaces, you may rewrite the latter like

        system qw|perl -pib -e "s/CAT/mouse/g" 'D:\tmp\file.txt'|;

        but pay attention in the general case! Whatever, in both cases you may have an OS quoting problem: you're giving perl a cmd line argument of 'D:\tmp\file.txt' which it will interpret literally as a filename, much different from D:\tmp\file.txt as you can see for yourself:

        C:\temp>perl -lpe "" foo.txt foo bar C:\temp>perl -lpe "" 'foo.txt' Can't open 'foo.txt': No such file or directory.
        If you can't understand the incipit, then please check the IPB Campaign.
Re: System call in Windows
by runrig (Abbot) on Oct 24, 2008 at 19:35 UTC
    You have a problem with quoting. Try (this provides system() with multiple arguments):
    system qw(perl -pib -e s/CAT/mouse/g D:\tmp\file.txt); # Or in case you need to replace an arg with a variable, then start wi +th: system "perl", "-pib", "-e", "s/CAT/mouse/g", 'D:\tmp\file.txt';
      Hi runrig,
      Your solution also works for me. Thank very much!
Re: System call in Windows
by krusty (Hermit) on Oct 24, 2008 at 19:33 UTC
    Try the following:
    #!/usr/bin/perl while (<>){ s/CAT/mouse/g; print; }

    Then run the code like so:
    prompt> perl -w 'D:\tmp\file.txt' > D:\tmp\file.txt

    Update: Thanks for the reference to the -pi flags. I understand now. The while loop is superfluous with the -p and the -i will edit the file given in place. Why does he need a system() function call around the whole thing? Won't that spawn another shell?
      If the OP fixed the quoting, then the file would be opened, read, and written to. Look at the -p and -i options in perlrun.


      Won't that spawn another shell?

      Yes, and you could do it without spawning another shell, with a bit more code. But the -p and -i flags make the job convenient, and if the OP doesn't care about the extra process, then neither do I :-)

      Hello krusty,
      Thanks for the suggestion. It's a good work around and I'll definitely use it in some other case. But what part of what I'm trying to do is also provide variables in the replacement so instead of CAT and mouse I would have "$var1" and "$var2".
      Thanks again!
      I myself wouldn't have wanted the overhead of a system call to start another perl interpreter, but it sounded like the OP was porting over something that had worked in UNIX to WinDoze, so I answered his basic question about that.
Re: System call in Windows
by csarid (Sexton) on Oct 24, 2008 at 20:42 UTC
    Sorry I'm new to the forum

    Just wanted to thank everyone for your help. All the solutions posted worked and are great!

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://719410]
Approved by CardinalNumber
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others exploiting the Monastery: (4)
As of 2018-04-23 19:40 GMT
Find Nodes?
    Voting Booth?