In most scripting languages (e.g. Ruby, Python, etc.) the package manager (e.g. gem, pip, etc.) can install scripts as executables and link them to a directory referenced in the PATH variable (e.g. /usr/local/bin). This turns those executable scripts into shell commands that the user can run in an standalone manner and outside the programming interface.
I wonder if there is such a possibility in R as well. Given that R uses standard Makefiles, I guess there must be a way to do so, albeit a non-standard one. I already know we can read command line arguments in a R script using the docopt
package. But is there a way to install the script as an executable upon the installation of a package?
It would be great to have a lead on this topic, but a single working example from CRAN would suffice as well.
I had a similar goal, this was the solution I settled on. I added a function to my R package that goes through and (verbosely) creates symlinks from ~/.local/bin
to each script in my packages exec
folder.
Other sensible default locations might be ~/.local/lib/R/bin
or ~/bin
, but I like ~/.local/bin
the best.
So after installing the package, I direct users to run
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))
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With