【问题标题】:Specify which shell to use in R指定在 R 中使用哪个 shell
【发布时间】:2023-04-02 00:33:01
【问题描述】:

我必须在 R 中运行一个 shell 脚本。我考虑过使用 R 的 system 函数。

但是,我的脚本涉及 source activate 和 /bin/sh shell 中不可用的其他命令。有没有办法我可以使用 /bin/bash 代替?

谢谢!

【问题讨论】:

  • 是的:system("/bin/bash my_script.sh")

标签: r bash shell


【解决方案1】:

调用/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")

那么传递给systemsystem2函数的命令应该使用指定的shell来调用。

【讨论】:

  • 我尝试了您的最后一个选项,但仍然无法正常工作(在我的情况下,我正在尝试设置 zsh,这是我的 macOS 中的默认设置)。实际上,如果我运行“Sys.getenv("SHELL")”,我会得到“/bin/zsh”,但是使用 system() 传递的命令仍然使用 bash。
  • @FranVillamil,您是否尝试过将 shell 命令放入带有 shebang 的可执行文件中,然后通过 system("/path/to/script.sh") 调用它?
  • 是的,但我还是有问题。我认为这可能与此有关(superuser.com/questions/1642933/r-and-shell-in-macos-catalina)以及我对 shell 的不了解。
猜你喜欢
  • 1970-01-01
  • 2017-07-21
  • 2017-09-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多