Calling External Program from R with Multiple Commands in System

in R, invoke external program in path with spaces with command line parameters

Try system2 as it does not use the cmd line processor and use r"{...}" to avoid having to double backslashes. This assumes R 4.0 or later. See ?Quotes for the full definition of the quotes syntax.

chimera <- r"{C:\Program Files\Chimera1.15\bin\chimera.exe}"
system2(chimera, c("--nogui", "myscript"))

For example, this works for me (you might need to change the path):

R <- r"{C:\Program Files\R\R-4.1\bin\x64\Rgui.exe}"  # modify as needed
system2(R, c("abc", "def"))

and when Rgui is launched we can verify that the arguments were passed by running this in the new instance of R:

commandArgs()
## [1] "C:\\PROGRA~1\\R\\R-4.1\\bin\\x64\\Rgui.exe"
## [2] "abc"
## [3] "def"

system

Alternately use system but put quotes around the path so that cmd interprets it correctly -- if it were typed into the Windows cmd line the quotes would be needed too.

system(r"{"C:\Program Files\Chimera1.15\bin\chimera.exe" --nogui myscript}")

Calling multiple commands via system() under windows doesn't work

Each call of system() creates it's own shell as a subprocess, that's why multiple subsequent system() calls don't work if you e.g. try to set shell variables or do a cd command (expecting subsequent commands running in a specific directory).

The easiest way to do it, is to create a little temporary script file containing all the commands and execute this one with a single system() call:

// A raw string literal to make escaping easier 
// (see https://en.cppreference.com/w/cpp/language/string_literal)
std::string cmds = R"xxx(
adb kill-server
adb devices
adb start-server &
var=$(adb shell "pidof com.rok")
AFTER=`echo $var | sed 's/\r//g'`
echo "$AFTER"
adb shell "kill -STOP $AFTER"
adb shell sleep 2
adb shell "kill -CONT $AFTER"
)xxx";

std::ofstream cmdFile("tempCmdFile.cmd");

cmdFile << cmds;
cmdFile.close();

system("tempCmdFile.cmd");

You probably should tidy up the tempCmdFile.cmd up afterwards (i.e. remove it). But I hope you grasp what the code above does.

Also I am not so sure that

AFTER=`echo $var | sed 's/\r//g'`

will work in a windows shell, as you expect it to do. You probably need a different solution for that, or a *nix like shell to run it (e.g. MinGw provides one).

Sending system command with arguments in R

You can use

command = paste(
"export $(dbus-launch); \
export NSS_USE_SHARED_DB=ENABLED; \
libreoffice --calc",
FILE )
system(command)

How do I execute a program or call a system command?

Solution:

Step #1: Add module

Use the subprocess module in the standard library:

import subprocess
subprocess.run(["ls", "-l"])

[This module allows you to spawn new processes, connect to their input/output/error pipes, and obtain their return codes. Read more via: subprocess]

Step #2: Call an external command

The simplest way to call an external command is to use the subprocess.run() function, which runs the specified command and waits for it to complete. Here's the demo code with an output:

import subprocess

result = subprocess.run(["ls"], capture_output=True)
print(result.stdout)

Advantage:
The advantage of subprocess.run over os.system is that it is more flexible (you can get the stdout, stderr, the "real" status code, better error handling, etc...).

Tip:
The shlex.split() method can be used to break down simple shell commands into individual arguments. But it may not work correctly with longer and more complex commands that include pipe symbols. This can make debugging difficult. To avoid this issue, the shell=True argument can be used, however, this approach has potential security risks.

Another way:
You can also use other functions like subprocess.Popen() to run a command and also redirect the stdout and stderr to a pipe, and you can also redirect the input to the process.

Security implications:
While running external commands, you should be careful to properly escape any arguments that contain special characters, as they might be interpreted by the shell in unexpected ways.


Learning resources:
Even the documentation for os.system recommends using subprocess instead:

The subprocess module provides more powerful facilities for spawning new processes and retrieving their results; using that module is preferable to using this function. See the Replacing Older Functions with the subprocess Module section in the subprocess documentation for some helpful recipes.


Note:
On Python 3.4 and earlier, use subprocess.call instead of .run:

subprocess.call(["ls", "-l"])

If using Python 3.5 +, use subprocess.run().



Related Topics



Leave a reply



Submit