【问题标题】:Installing executable scripts with R package使用 R 包安装可执行脚本
【发布时间】:2017-06-15 11:15:16
【问题描述】:

在大多数脚本语言(例如 Ruby、Python 等)中,包管理器(例如 gem、pip 等)可以将脚本安装为可执行文件并将它们链接到 PATH 变量中引用的目录(例如 /usr/local /垃圾桶)。这会将这些可执行脚本转换为用户可以在编程接口之外以独立方式运行的 shell 命令。

我想知道 R 中是否也有这种可能性。鉴于 R 使用标准 Makefile,我想一定有办法做到这一点,尽管是非标准的。我已经知道我们可以在 R 脚本using the docopt package 中读取命令行参数。但是有没有办法在安装包时将脚本安装为可执行文件?

在这个主题上有一个领导者会很棒,但是 CRAN 的一个工作示例也足够了。

【问题讨论】:

    标签: r deployment packages executable


    【解决方案1】:

    我也有类似的目标,这是我确定的解决方案。我在我的 R 包中添加了一个函数,该函数通过并(详细地)创建从 ~/.local/bin 到我的包 exec 文件夹中的每个脚本的符号链接。

    其他合理的默认位置可能是~/.local/lib/R/bin~/bin,但我最喜欢~/.local/bin

    所以安装包后,我引导用户运行

    Rscript -e 'mypackage::install_executable_scripts()'
    
    #' @export
    install_executable_scripts <- function(into = "~/.local/bin", overwrite = FALSE) {
      scripts <- dir(system.file("exec", package = "mypackage"),
                     full.names = TRUE)
      if (!dir.exists(into)) dir.create(into)
      into <- normalizePath(into)
    
      dests <- file.path(normalizePath(into), basename(scripts))
      if (any(already_exist <- file.exists(dests))) {
        if (overwrite) {
          to_del <- dests[already_exist]
          cli::cat_bullet("Deleting existing file: ", to_del,
                          bullet_col = "red")
          unlink(to_del)
        } else {
          cli::cat_bullet(sprintf(
            "Skipping script '%s' because a file by that name already exists at the destination",
            basename(scripts[already_exist])))
          scripts <- scripts[!already_exist]
          dests   <-   dests[!already_exist]
        }
      }
      if (length(scripts)) {
        file.symlink(scripts, dests)
        cli::cat_line("Created symlinks:")
        cli::cat_bullet(dests, " ->\n    ", scripts, bullet_col = "green")
      } else
        cli::cat_line("Nothing installed")
    
      PATHS <- normalizePath(strsplit(Sys.getenv("PATH"), ":", fixed = TRUE)[[1]],
                             mustWork = FALSE)
      if(!into %in% PATHS)
        warning(sprintf("destination '%s' is not on the PATH", into))
    }
    

    【讨论】:

      【解决方案2】:

      简短(非常悲伤)的回答:你不能。但请继续阅读。

      推理:R 只会将包内容写入其自己的.libPaths() 目录(或第一个,以防多个目录),或用户指定的目录。

      所以,比如说,/usr/local/bin/ 是遥不可及的。这是一个可以防御的策略。

      这也是相当可悲的——我写了littler(也是CRAN page)正是为了这个目的:可执行的 R 脚本。我们有几十个来自cron工作的工作人员。那么我们该怎么办?从包含脚本的包的scripts/ 子目录到/usr/local/bin一次性软链接。在软件包升级时,该链接作为软链接保留。

      这就是我为例如所有examples shipping with littler 以及其他包中的更多内容所做的。他们中的许多人也使用docopt

      【讨论】:

      • 但是在 R 的.libPaths() 下是否有一个标准的 bin 路径,我们可以一次性添加到路径中,然后将我们所有的可执行文件链接到那里?这就是pipgem 的作用。
      • 只需展开.libPaths():它是高于所有包目录的一层。
      猜你喜欢
      • 2011-10-18
      • 1970-01-01
      • 2015-05-06
      • 1970-01-01
      • 1970-01-01
      • 2016-01-25
      • 2013-07-22
      • 2011-05-02
      相关资源
      最近更新 更多