【发布时间】:2023-04-02 00:33:01
【问题描述】:
我必须在 R 中运行一个 shell 脚本。我考虑过使用 R 的 system 函数。
但是,我的脚本涉及 source activate 和 /bin/sh shell 中不可用的其他命令。有没有办法我可以使用 /bin/bash 代替?
谢谢!
【问题讨论】:
-
是的:
system("/bin/bash my_script.sh")
我必须在 R 中运行一个 shell 脚本。我考虑过使用 R 的 system 函数。
但是,我的脚本涉及 source activate 和 /bin/sh shell 中不可用的其他命令。有没有办法我可以使用 /bin/bash 代替?
谢谢!
【问题讨论】:
system("/bin/bash my_script.sh")
调用/bin/bash,并通过-c选项以下列方式之一传递命令:
system(paste("/bin/bash -c", shQuote("Bash commands")))
system2("/bin/bash", args = c("-c", shQuote("Bash commands")))
如果您只想运行 Bash 文件,请为其提供 shebang,例如:
#!/bin/bash -
builtin printf %q "/tmp/a b c"
并通过将脚本的路径传递给system 函数来调用它:
system("/path/to/script.sh")
暗示当前用户/组有足够的permissions来执行脚本。
之前我建议设置SHELL 环境变量。但这可能行不通,因为 R 中 system 函数的实现调用了同名的 the C function(参见 src/main/sysutils.c):
int R_system(const char *command)
{
/*... */
res = system(command);
和
system()库函数使用fork(2)创建一个子进程,该子进程执行使用execl(3)的命令中指定的shell 命令,如下所示:
execl("/bin/sh", "sh", "-c", command, (char *) 0);
(见man 3 system)
因此,您应该调用/bin/bash,并通过-c 选项传递脚本主体。
让我们使用 Bash 特定的 mapfile 列出 /tmp 中的顶级目录:
test.R
script <- '
mapfile -t dir < <(find /tmp -mindepth 1 -maxdepth 1 -type d)
for d in "${dir[@]}"
do
builtin printf "%s\n" "$d"
done > /tmp/out'
system2("/bin/bash", args = c("-c", shQuote(script)))
test.sh
Rscript test.R && cat /tmp/out
样本输出
/tmp/RtmpjJpuzr
/tmp/fish.ruslan
...
尝试设置SHELL环境变量:
Sys.setenv(SHELL = "/bin/bash")
system("command")
那么传递给system或system2函数的命令应该使用指定的shell来调用。
【讨论】:
system("/path/to/script.sh") 调用它?