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
Programming with Ggplot2 and Dplyr
Saving a File to Sharepoint with R
Why Is R Dplyr::Mutate Inconsistent with Custom Functions
Unpacking and Merging Lists in a Column in Data.Frame
Remove Some of the Axis Labels in Ggplot Faceted Plots
Inserting Stargazer or Xable Table into Knitr Document
Font Awesome in R, Loaded But Not Found by Waffle
R: Row-Wise Dplyr::Mutate Using Function That Takes a Data Frame Row and Returns an Integer
R: Interactive Plots (Tooltips): Rcharts Dimple Plot: Formatting Axis
Control Number Formatting in Shiny's Implementation of Datatable
Plot Margins in Rmarkdown/Knitr
Split Data.Frame into Groups by Column Name
Knitr Inline Chunk Options (No Evaluation) or Just Render Highlighted Code
Search for Corresponding Node in a Regression Tree Using Rpart
Differencebetween Scale Transformation and Coordinate System Transformation