in reply to Re: use of Backticks to catch console output
in thread use of Backticks to catch console output

If you want something a little more robust, that avoids the overhead of using the shell, consider capturex() from IPC::System::Simple.

It is indeed much more robust and a good suggestion! Just a small nitpick: on Windows it is almost impossible to avoid the shell*. IPC::System::Simple works around this by using Win32::ShellQuote under the hood.

* Update: See my clarification further down in the thread.

  • Comment on Re^2: use of Backticks to catch console output

Replies are listed 'Best First'.
Re^3: use of Backticks to catch console output
by kcott (Archbishop) on Dec 11, 2022 at 14:11 UTC

    G'day haukex,

    "Just a small nitpick: on Windows it is almost impossible to avoid the shell."

    I checked out that module's documentation and code not so long; I've just checked again. Both are still very clear that capturex() does not invoke the shell. Here's a selection of extracts (non-exhaustive):

    From SYNOPSIS:

    # As above, but NEVER invokes the shell. my $output = capturex("some_command", @args);

    From source, starting at Line 361 (note the "NO_SHELL"):

    # capturex() is just like backticks/qx, but never invokes the shell. sub capturex { ... if (WINDOWS) { return _win32_capture(NO_SHELL, $valid_returns, $command, +@args); }

    Are you possibly confusing capturex() with capture()? Same source, starting at Line 220 (note the "USE_SHELL"):

    # capture is our way of running a process with backticks/qx semantics sub capture { ... if (WINDOWS) { # USE_SHELL really means "You may use the shell if you nee +d it." return _win32_capture(USE_SHELL, $valid_returns, $command) +; }

    If not a case of confusion, do you think the documentation, code, or something else, is wrong?

    All links and extracts are from the IPC-System-Simple-1.30 distribution (released "Mar 24, 2020").

    — Ken

      From source, ...

      You need to trace the source a little further and look into _win32_capture, where you'll see that Win32::ShellQuote gets called no matter what the value of $use_shell is.

      Both are still very clear that capturex() does not invoke the shell.

      In my experience the documentation of such modules is usually tailored to *NIX. Either that or people eqate using Win32::ShellQuote to "avoiding the shell"*, which isn't quite accurate, and the module does have some edge cases that means it's not the same as execvp on *NIX - like I said, I was being nitpicky :-)

      Have a look at Re^2: Having to manually escape quote character in args to "system"? for more details on calling commands on Windows and why argument quoting is such an issue there.

      * Update: See my clarification further down in the thread.

        No, I'm still not seeing it. I'm not at all familiar with modules in the Win32:: namespace; perhaps you can help me out with this.

        "... you'll see that Win32::ShellQuote gets called ..."

        Win32::ShellQuote is a module and gets loaded; I've checked the code and don't see that operation invoking a shell. Win32::ShellQuote::quote_native() gets conditionally called; again, I've checked the code and don't see that operation invoking a shell either.

        quote_native() appears within _spawn_or_die(). Looking into that routine, I see Win32::Process::Create() is called. There's XS code under the hood (I have pretty much zero XS expertise); perhaps a shell is invoked here.

        The impression I get is that Win32::Process::Create() is doing what it's name suggests, i.e. creates a process. If a *nix system, open(my $pipe, '-|') would be used, which also creates (forks) a process.

        — Ken