R 脚本中的 here() 问题
here() issue in R scripts
这里是 R 脚本中的问题
我想了解 here() 如何以可移植的方式工作。找到它:查看稍后在 最终答案下的工作原理 - TL;DR - 最重要的是,here()
并不是那么有用 运行宁一个 script.R
来自命令行。
我在 JBGruber 的帮助下理解它的方式:here()
查找项目的根目录(例如,RStudio 项目、Git 项目或使用 .here 文件定义的其他项目) 从当前工作目录开始 并向上移动直到找到任何项目。如果它没有找到任何东西,它会回退到使用完整的工作目录。如果 cron 的脚本 运行 将默认为我的主目录。当然,可以通过 cron 命令将目录作为参数传递,但这相当麻烦。下面的答案提供了很好的解释,我在“最终答案”部分总结了我发现最直接有用的内容。但是请不要误会,Nicola 的回答非常好,也很有帮助。
原创 Objective - 写了一套R脚本,包括R-markdown .Rmd
这样我就可以压缩目录,发给别人它会在他们的计算机上 运行。可能在非常低端的计算机上 - 例如 RaspberryPi 或旧硬件 运行ning linux.
条件:
- 可以通过
Rscript
从命令行 运行
- 如上,但通过
cron
安排
- 设置工作目录的主要方法是
set_here()
- 从控制台执行一次,然后文件夹是可移植的,因为 .here
文件包含在压缩目录中。
- 不需要
Rstudio
- 因此不想做 R 项目
- 可以也可以运行与
Rstudio
交互(开发)
- 可以从
shiny
开始执行(我假设满足以上条件就OK了)
我特别不想创建 Rstudio 项目,因为在我看来它需要安装和使用 Rstudio,但我希望我的脚本尽可能可移植并且 运行 在低资源、无头平台上。
示例代码:
让我们假设工作目录 myGoodScripts
如下:
/Users/john/src/myGoodScripts/
开始开发时,我会使用 setwd()
进入上述目录并执行 set_here()
以创建 .here
文件。然后有2个脚本dataFetcherMailer.R
,dataFetcher.Rmd
和一个子目录bkp
:
dataFetcherMailer.R
library(here)
library(knitr)
basedir <- here()
# this is where here should give path to .here file
rmarkdown::render(paste0(basedir,"/dataFetcher.Rmd"))
# email the created report
# email_routine_with_gmailr(paste0(basedir,"dataFetcher.pdf"))
# now substituted with verification that a pdf report was created
file.exists(paste0(basedir,"/dataFetcher.pdf"))
dataFetcher.Rmd
---
title: "Data collection control report"
author: "HAL"
date: "`r Sys.Date()`"
output: pdf_document
---
```{r setup, include=FALSE}
library(knitr)
library(here)
basedir <- here()
# in actual program this reads data from a changing online data source
df.main <- mtcars
# data backup
datestamp <- format(Sys.time(),format="%Y-%m-%d_%H-%M")
backupName <- paste0(basedir,"/bkp/dataBackup_",datestamp,"csv.gz")
write.csv(df.main, gzfile(backupName))
```
# This is data collection report
Yesterday's data total records: `r nrow(df.main)`.
The basedir was `r basedir`
The current directory is `r getwd()`
The here path is `r here()`
我猜报告中的最后 3 行是匹配的。即使 getwd()
与其他两个不匹配,也没关系,因为 here()
将确保绝对基本路径。
错误
当然 - 以上方法不起作用。它只有在我从同一个 myGoodScripts/
目录执行 Rscript ./dataFetcherMailer.R
时才有效。
我的目标 是了解如何执行脚本,以便相对于脚本位置解析相对路径,并且脚本可以 运行 来自独立于命令行的当前工作目录。我现在可以从 bash 运行 执行此操作,前提是我已对包含脚本的目录执行 cd
操作。如果我安排 cron
执行脚本,则默认工作目录将为 /home/user
并且脚本失败。我天真的方法是不管 shell 的当前工作目录 basedir <- here()
应该给出一个可以解析相对路径的文件系统点是行不通的。
来自 Rstudio,无需事先 setwd()
here() starts at /home/user
Error in abs_path(input) :
The file '/home/user/dataFetcher.Rmd' does not exist.
如果 cwd 未设置为脚本目录,则来自 bash 和 Rscript
。
$ cd /home/user/scrc
$ Rscript ./myGoodScripts/dataFetcherMailer.R
here() starts at /home/user/src
Error in abs_path(input) :
The file '/home/user/src/dataFetcher.Rmd' does not exist.
Calls: <Anonymous> -> setwd -> dirname -> abs_path
如果有人能帮助我理解并解决这个问题,那就太好了。如果存在另一种设置没有 here()
的基本路径的可靠方法,我很想知道。最终从 Rstudio
执行脚本比了解如何从 commandline/cron
.
执行此类脚本重要得多
自 JBGruber 回答以来的更新:
我稍微修改了函数,以便它可以 return 文件的文件名或目录。我目前正在尝试修改它,以便当 .Rmd
文件从 Rstudio 编织时它可以工作,同样地 运行 通过 R 文件编织。
here2 <- function(type = 'dir') {
args <- commandArgs(trailingOnly = FALSE)
if ("RStudio" %in% args) {
filepath <- rstudioapi::getActiveDocumentContext()$path
} else if ("interactive" %in% args) {
file_arg <- "--file="
filepath <- sub(file_arg, "", grep(file_arg, args, value = TRUE))
} else if ("--slave" %in% args) {
string <- args[6]
mBtwSquotes <- "(?<=')[^']*[^']*(?=')"
filepath <- regmatches(string,regexpr(mBtwSquotes,string,perl = T))
} else if (pmatch("--file=" ,args)) {
file_arg <- "--file="
filepath <- sub(file_arg, "", grep(file_arg, args, value = TRUE))
} else {
if (type == 'dir') {
filepath <- '.'
return(filepath)
} else {
filepath <- "error"
return(filepath)
}
}
if (type == 'dir') {
filepath <- dirname(filepath)
}
return(filepath)
}
然而我发现 commandArgs()
是从 R 脚本继承的,即当 .Rmd
文档从 script.R
编织时它们保持不变。因此只有 script.R
位置的 basepath
可以通用,而不是文件名。换句话说,当放置在 .Rmd
文件中时,此函数将指向调用 script.R
路径而不是 .Rmd
文件路径。
最终答案 (TL;DR)
因此,此函数的较短版本会更有用:
here2 <- function() {
args <- commandArgs(trailingOnly = FALSE)
if ("RStudio" %in% args) {
# R script called from Rstudio with "source file button"
filepath <- rstudioapi::getActiveDocumentContext()$path
} else if ("--slave" %in% args) {
# Rmd file called from Rstudio with "knit button"
# (if we placed this function in a .Rmd file)
file_arg <- "rmarkdown::render"
string <- grep(file_arg, args, value = TRUE)
mBtwQuotes <- "(?<=')[^']*[^']*(?=')"
filepath <- regmatches(string,regexpr(mBtwQuotes,string,perl = T))
} else if ((sum(grepl("--file=" ,args))) >0) {
# called in some other way that passes --file= argument
# R script called via cron or commandline using Rscript
file_arg <- "--file="
filepath <- sub(file_arg, "", grep(file_arg, args, value = TRUE))
} else if (sum(grepl("rmarkdown::render" ,args)) >0 ) {
# Rmd file called to render from commandline with
# Rscript -e 'rmarkdown::render("RmdFileName")'
file_arg <- "rmarkdown::render"
string <- grep(file_arg, args, value = TRUE)
mBtwQuotes <- "(?<=\")[^\"]*[^\"]*(?=\")"
filepath <- regmatches(string,regexpr(mBtwQuotes,string,perl = T))
} else {
# we do not know what is happening; taking a chance; could have error later
filepath <- normalizePath(".")
return(filepath)
}
filepath <- dirname(filepath)
return(filepath)
}
NB: 从 .Rmd
文件中到达文件的包含目录调用 normalizePath(".")
就足够了 - 无论你调用来自脚本、命令行或 Rstudio 的 .Rmd
文件。
你问的是什么
here()
的行为并不是您真正想要的,我认为。相反,您正在寻找的是确定源文件的路径,也就是 .R
文件。我对 here()
命令进行了一些扩展,以按照您期望的方式运行:
here2 <- function() {
args <- commandArgs(trailingOnly = FALSE)
if ("RStudio" %in% args) {
dirname(rstudioapi::getActiveDocumentContext()$path)
} else {
file_arg <- "--file="
filepath <- sub(file_arg, "", grep(file_arg, args, value = TRUE))
dirname(filepath)
}
}
在 RStudio 中脚本不是 运行 的情况的想法来自 this answer。我通过将函数定义粘贴到 dataFetcherMailer.R
文件的开头来尝试这样做。您也可以考虑将它放在您的主目录中的另一个文件中,并使用例如 source("here2.R")
而不是 library(here)
来调用它,或者您可以为此目的编写一个小的 R 包。
r0berts 的最终版本(op)
here2 <- function() {
args <- commandArgs(trailingOnly = FALSE)
if ("RStudio" %in% args) {
# R script called from Rstudio with "source file button"
filepath <- rstudioapi::getActiveDocumentContext()$path
} else if ("--slave" %in% args) {
# Rmd file called from Rstudio with "knit button"
# (if we placed this function in a .Rmd file)
file_arg <- "rmarkdown::render"
string <- grep(file_arg, args, value = TRUE)
mBtwQuotes <- "(?<=')[^']*[^']*(?=')"
filepath <- regmatches(string,regexpr(mBtwQuotes,string,perl = T))
} else if ((sum(grepl("--file=" ,args))) >0) {
# called in some other way that passes --file= argument
# R script called via cron or commandline using Rscript
file_arg <- "--file="
filepath <- sub(file_arg, "", grep(file_arg, args, value = TRUE))
} else if (sum(grepl("rmarkdown::render" ,args)) >0 ) {
# Rmd file called to render from commandline with
# Rscript -e 'rmarkdown::render("RmdFileName")'
file_arg <- "rmarkdown::render"
string <- grep(file_arg, args, value = TRUE)
mBtwQuotes <- "(?<=\")[^\"]*[^\"]*(?=\")"
filepath <- regmatches(string,regexpr(mBtwQuotes,string,perl = T))
} else {
# we do not know what is happening; taking a chance; could have error later
filepath <- normalizePath(".")
return(filepath)
}
filepath <- dirname(filepath)
return(filepath)
}
我认为大多数人实际需要的东西
我不久前发现了这种方法,但后来实际上完全改变了我的工作流程,只使用 R Markdown 文件(和 RStudio 项目)。这样做的优点之一是 Rmd 文件的工作目录始终是该文件的位置。因此,您不必为设置工作目录而烦恼,只需在脚本中编写相对于 Rmd 文件位置的所有路径即可。
---
title: "Data collection control report"
author: "HAL"
date: "`r Sys.Date()`"
output: pdf_document
---
```{r setup, include=FALSE}
library(knitr)
# in actual program this reads data from a changing online data source
df.main <- mtcars
# data backup
datestamp <- format(Sys.time(),format="%Y-%m-%d_%H-%M")
# create bkp folder if it doesn't exist
if (!dir.exists(paste0("./bkp/"))) dir.create("./bkp/")
backupName <- paste0("./bkp/dataBackup_", datestamp, "csv.gz")
write.csv(df.main, gzfile(backupName))
```
# This is data collection report
Yesterday's data total records: `r nrow(df.main)`.
The current directory is `r getwd()`
注意以./
开头的路径表示从Rmd文件的文件夹开始。 ../
表示您升级了一个级别。 ../../
你往上两层等等。因此,如果您的 Rmd 文件位于根文件夹中名为“scripts”的文件夹中,并且您想将数据保存在根文件夹中名为“data”的文件夹中,则可以编写 saveRDS(data, "../data/dat.RDS")
.
您可以 运行 来自命令 line/cron 和 Rscript -e 'rmarkdown::render("/home/johannes/Desktop/myGoodScripts/dataFetcher.Rmd")'
的 Rmd 文件。
虽然您的问题需要使用 here
包,但我提出了一个不需要它的解决方案。我认为它更干净,同样便携。
如果我的理解是正确的,您希望您的脚本知道它们的位置。这很好,但在大多数情况下是不必要的,因为脚本的调用者 必须 知道脚本所在的位置才能实际调用它,并且您可以利用这些知识。所以:
- 摆脱所有
here
电话;
- 不要试图在您的脚本中确定文件位置,而只需将每个路径写为相对于您的文件夹的根目录(就像您在开发中所做的那样)。
接下来,有几个选项。
第一个,最小的,就是不要注册到 cron
裸 Rstudio /path/to/yourfolder/yourscript.R
,而是创建一个 bash 脚本如下(我们称之为 script.sh
):
#!/bin/sh
cd /path/to/yourfolder
Rscript yourscript.R
并将此脚本注册到 crontab
。当您指示执行上述操作时,您可以将 README
文件添加到您的文件夹中(类似于:“将文件夹解压缩到您想要的任何位置,记下路径,构建一个 script.sh
文件并对其进行 crotab” ).当然,使用 Rstudio,您可以以通常的方式打开并 运行 文件(setwd
然后 运行 它;您将其记录在 README
中)。
第二种是编写“安装程序”(您可以选择 makefile
、简单的 R 脚本、bash 文件或其他),它会自动执行上述操作。它只是执行这些步骤。
- 在 homedir 下创建一个文件夹,类似于
.robertsProject
(注意圆点更可能是该目录不存在)。
- 将文件夹中的所有文件和目录复制到这个新创建的文件夹中。
- 创建一个
.sh
文件,就像上面的文件一样(请注意,您知道要将文件移动到哪里以及它们的位置,因此您可以在脚本中写入正确的路径)。
- 将
.sh
文件注册到 crontab。
完成!收到该文件的人只需 运行 安装一次此安装程序(您将在 README 中记录如何安装),他们就可以使用您的工具。
这里是 R 脚本中的问题
我想了解 here() 如何以可移植的方式工作。找到它:查看稍后在 最终答案下的工作原理 - TL;DR - 最重要的是,here()
并不是那么有用 运行宁一个 script.R
来自命令行。
我在 JBGruber 的帮助下理解它的方式:here()
查找项目的根目录(例如,RStudio 项目、Git 项目或使用 .here 文件定义的其他项目) 从当前工作目录开始 并向上移动直到找到任何项目。如果它没有找到任何东西,它会回退到使用完整的工作目录。如果 cron 的脚本 运行 将默认为我的主目录。当然,可以通过 cron 命令将目录作为参数传递,但这相当麻烦。下面的答案提供了很好的解释,我在“最终答案”部分总结了我发现最直接有用的内容。但是请不要误会,Nicola 的回答非常好,也很有帮助。
原创 Objective - 写了一套R脚本,包括R-markdown .Rmd
这样我就可以压缩目录,发给别人它会在他们的计算机上 运行。可能在非常低端的计算机上 - 例如 RaspberryPi 或旧硬件 运行ning linux.
条件:
- 可以通过
Rscript
从命令行 运行
- 如上,但通过
cron
安排
- 设置工作目录的主要方法是
set_here()
- 从控制台执行一次,然后文件夹是可移植的,因为.here
文件包含在压缩目录中。 - 不需要
Rstudio
- 因此不想做 R 项目 - 可以也可以运行与
Rstudio
交互(开发) - 可以从
shiny
开始执行(我假设满足以上条件就OK了)
我特别不想创建 Rstudio 项目,因为在我看来它需要安装和使用 Rstudio,但我希望我的脚本尽可能可移植并且 运行 在低资源、无头平台上。
示例代码:
让我们假设工作目录 myGoodScripts
如下:
/Users/john/src/myGoodScripts/
开始开发时,我会使用 setwd()
进入上述目录并执行 set_here()
以创建 .here
文件。然后有2个脚本dataFetcherMailer.R
,dataFetcher.Rmd
和一个子目录bkp
:
dataFetcherMailer.R
library(here)
library(knitr)
basedir <- here()
# this is where here should give path to .here file
rmarkdown::render(paste0(basedir,"/dataFetcher.Rmd"))
# email the created report
# email_routine_with_gmailr(paste0(basedir,"dataFetcher.pdf"))
# now substituted with verification that a pdf report was created
file.exists(paste0(basedir,"/dataFetcher.pdf"))
dataFetcher.Rmd
---
title: "Data collection control report"
author: "HAL"
date: "`r Sys.Date()`"
output: pdf_document
---
```{r setup, include=FALSE}
library(knitr)
library(here)
basedir <- here()
# in actual program this reads data from a changing online data source
df.main <- mtcars
# data backup
datestamp <- format(Sys.time(),format="%Y-%m-%d_%H-%M")
backupName <- paste0(basedir,"/bkp/dataBackup_",datestamp,"csv.gz")
write.csv(df.main, gzfile(backupName))
```
# This is data collection report
Yesterday's data total records: `r nrow(df.main)`.
The basedir was `r basedir`
The current directory is `r getwd()`
The here path is `r here()`
我猜报告中的最后 3 行是匹配的。即使 getwd()
与其他两个不匹配,也没关系,因为 here()
将确保绝对基本路径。
错误
当然 - 以上方法不起作用。它只有在我从同一个 myGoodScripts/
目录执行 Rscript ./dataFetcherMailer.R
时才有效。
我的目标 是了解如何执行脚本,以便相对于脚本位置解析相对路径,并且脚本可以 运行 来自独立于命令行的当前工作目录。我现在可以从 bash 运行 执行此操作,前提是我已对包含脚本的目录执行 cd
操作。如果我安排 cron
执行脚本,则默认工作目录将为 /home/user
并且脚本失败。我天真的方法是不管 shell 的当前工作目录 basedir <- here()
应该给出一个可以解析相对路径的文件系统点是行不通的。
来自 Rstudio,无需事先 setwd()
here() starts at /home/user
Error in abs_path(input) :
The file '/home/user/dataFetcher.Rmd' does not exist.
如果 cwd 未设置为脚本目录,则来自 bash 和 Rscript
。
$ cd /home/user/scrc
$ Rscript ./myGoodScripts/dataFetcherMailer.R
here() starts at /home/user/src
Error in abs_path(input) :
The file '/home/user/src/dataFetcher.Rmd' does not exist.
Calls: <Anonymous> -> setwd -> dirname -> abs_path
如果有人能帮助我理解并解决这个问题,那就太好了。如果存在另一种设置没有 here()
的基本路径的可靠方法,我很想知道。最终从 Rstudio
执行脚本比了解如何从 commandline/cron
.
自 JBGruber 回答以来的更新:
我稍微修改了函数,以便它可以 return 文件的文件名或目录。我目前正在尝试修改它,以便当 .Rmd
文件从 Rstudio 编织时它可以工作,同样地 运行 通过 R 文件编织。
here2 <- function(type = 'dir') {
args <- commandArgs(trailingOnly = FALSE)
if ("RStudio" %in% args) {
filepath <- rstudioapi::getActiveDocumentContext()$path
} else if ("interactive" %in% args) {
file_arg <- "--file="
filepath <- sub(file_arg, "", grep(file_arg, args, value = TRUE))
} else if ("--slave" %in% args) {
string <- args[6]
mBtwSquotes <- "(?<=')[^']*[^']*(?=')"
filepath <- regmatches(string,regexpr(mBtwSquotes,string,perl = T))
} else if (pmatch("--file=" ,args)) {
file_arg <- "--file="
filepath <- sub(file_arg, "", grep(file_arg, args, value = TRUE))
} else {
if (type == 'dir') {
filepath <- '.'
return(filepath)
} else {
filepath <- "error"
return(filepath)
}
}
if (type == 'dir') {
filepath <- dirname(filepath)
}
return(filepath)
}
然而我发现 commandArgs()
是从 R 脚本继承的,即当 .Rmd
文档从 script.R
编织时它们保持不变。因此只有 script.R
位置的 basepath
可以通用,而不是文件名。换句话说,当放置在 .Rmd
文件中时,此函数将指向调用 script.R
路径而不是 .Rmd
文件路径。
最终答案 (TL;DR)
因此,此函数的较短版本会更有用:
here2 <- function() {
args <- commandArgs(trailingOnly = FALSE)
if ("RStudio" %in% args) {
# R script called from Rstudio with "source file button"
filepath <- rstudioapi::getActiveDocumentContext()$path
} else if ("--slave" %in% args) {
# Rmd file called from Rstudio with "knit button"
# (if we placed this function in a .Rmd file)
file_arg <- "rmarkdown::render"
string <- grep(file_arg, args, value = TRUE)
mBtwQuotes <- "(?<=')[^']*[^']*(?=')"
filepath <- regmatches(string,regexpr(mBtwQuotes,string,perl = T))
} else if ((sum(grepl("--file=" ,args))) >0) {
# called in some other way that passes --file= argument
# R script called via cron or commandline using Rscript
file_arg <- "--file="
filepath <- sub(file_arg, "", grep(file_arg, args, value = TRUE))
} else if (sum(grepl("rmarkdown::render" ,args)) >0 ) {
# Rmd file called to render from commandline with
# Rscript -e 'rmarkdown::render("RmdFileName")'
file_arg <- "rmarkdown::render"
string <- grep(file_arg, args, value = TRUE)
mBtwQuotes <- "(?<=\")[^\"]*[^\"]*(?=\")"
filepath <- regmatches(string,regexpr(mBtwQuotes,string,perl = T))
} else {
# we do not know what is happening; taking a chance; could have error later
filepath <- normalizePath(".")
return(filepath)
}
filepath <- dirname(filepath)
return(filepath)
}
NB: 从 .Rmd
文件中到达文件的包含目录调用 normalizePath(".")
就足够了 - 无论你调用来自脚本、命令行或 Rstudio 的 .Rmd
文件。
你问的是什么
here()
的行为并不是您真正想要的,我认为。相反,您正在寻找的是确定源文件的路径,也就是 .R
文件。我对 here()
命令进行了一些扩展,以按照您期望的方式运行:
here2 <- function() {
args <- commandArgs(trailingOnly = FALSE)
if ("RStudio" %in% args) {
dirname(rstudioapi::getActiveDocumentContext()$path)
} else {
file_arg <- "--file="
filepath <- sub(file_arg, "", grep(file_arg, args, value = TRUE))
dirname(filepath)
}
}
在 RStudio 中脚本不是 运行 的情况的想法来自 this answer。我通过将函数定义粘贴到 dataFetcherMailer.R
文件的开头来尝试这样做。您也可以考虑将它放在您的主目录中的另一个文件中,并使用例如 source("here2.R")
而不是 library(here)
来调用它,或者您可以为此目的编写一个小的 R 包。
r0berts 的最终版本(op)
here2 <- function() {
args <- commandArgs(trailingOnly = FALSE)
if ("RStudio" %in% args) {
# R script called from Rstudio with "source file button"
filepath <- rstudioapi::getActiveDocumentContext()$path
} else if ("--slave" %in% args) {
# Rmd file called from Rstudio with "knit button"
# (if we placed this function in a .Rmd file)
file_arg <- "rmarkdown::render"
string <- grep(file_arg, args, value = TRUE)
mBtwQuotes <- "(?<=')[^']*[^']*(?=')"
filepath <- regmatches(string,regexpr(mBtwQuotes,string,perl = T))
} else if ((sum(grepl("--file=" ,args))) >0) {
# called in some other way that passes --file= argument
# R script called via cron or commandline using Rscript
file_arg <- "--file="
filepath <- sub(file_arg, "", grep(file_arg, args, value = TRUE))
} else if (sum(grepl("rmarkdown::render" ,args)) >0 ) {
# Rmd file called to render from commandline with
# Rscript -e 'rmarkdown::render("RmdFileName")'
file_arg <- "rmarkdown::render"
string <- grep(file_arg, args, value = TRUE)
mBtwQuotes <- "(?<=\")[^\"]*[^\"]*(?=\")"
filepath <- regmatches(string,regexpr(mBtwQuotes,string,perl = T))
} else {
# we do not know what is happening; taking a chance; could have error later
filepath <- normalizePath(".")
return(filepath)
}
filepath <- dirname(filepath)
return(filepath)
}
我认为大多数人实际需要的东西
我不久前发现了这种方法,但后来实际上完全改变了我的工作流程,只使用 R Markdown 文件(和 RStudio 项目)。这样做的优点之一是 Rmd 文件的工作目录始终是该文件的位置。因此,您不必为设置工作目录而烦恼,只需在脚本中编写相对于 Rmd 文件位置的所有路径即可。
---
title: "Data collection control report"
author: "HAL"
date: "`r Sys.Date()`"
output: pdf_document
---
```{r setup, include=FALSE}
library(knitr)
# in actual program this reads data from a changing online data source
df.main <- mtcars
# data backup
datestamp <- format(Sys.time(),format="%Y-%m-%d_%H-%M")
# create bkp folder if it doesn't exist
if (!dir.exists(paste0("./bkp/"))) dir.create("./bkp/")
backupName <- paste0("./bkp/dataBackup_", datestamp, "csv.gz")
write.csv(df.main, gzfile(backupName))
```
# This is data collection report
Yesterday's data total records: `r nrow(df.main)`.
The current directory is `r getwd()`
注意以./
开头的路径表示从Rmd文件的文件夹开始。 ../
表示您升级了一个级别。 ../../
你往上两层等等。因此,如果您的 Rmd 文件位于根文件夹中名为“scripts”的文件夹中,并且您想将数据保存在根文件夹中名为“data”的文件夹中,则可以编写 saveRDS(data, "../data/dat.RDS")
.
您可以 运行 来自命令 line/cron 和 Rscript -e 'rmarkdown::render("/home/johannes/Desktop/myGoodScripts/dataFetcher.Rmd")'
的 Rmd 文件。
虽然您的问题需要使用 here
包,但我提出了一个不需要它的解决方案。我认为它更干净,同样便携。
如果我的理解是正确的,您希望您的脚本知道它们的位置。这很好,但在大多数情况下是不必要的,因为脚本的调用者 必须 知道脚本所在的位置才能实际调用它,并且您可以利用这些知识。所以:
- 摆脱所有
here
电话; - 不要试图在您的脚本中确定文件位置,而只需将每个路径写为相对于您的文件夹的根目录(就像您在开发中所做的那样)。
接下来,有几个选项。
第一个,最小的,就是不要注册到 cron
裸 Rstudio /path/to/yourfolder/yourscript.R
,而是创建一个 bash 脚本如下(我们称之为 script.sh
):
#!/bin/sh
cd /path/to/yourfolder
Rscript yourscript.R
并将此脚本注册到 crontab
。当您指示执行上述操作时,您可以将 README
文件添加到您的文件夹中(类似于:“将文件夹解压缩到您想要的任何位置,记下路径,构建一个 script.sh
文件并对其进行 crotab” ).当然,使用 Rstudio,您可以以通常的方式打开并 运行 文件(setwd
然后 运行 它;您将其记录在 README
中)。
第二种是编写“安装程序”(您可以选择 makefile
、简单的 R 脚本、bash 文件或其他),它会自动执行上述操作。它只是执行这些步骤。
- 在 homedir 下创建一个文件夹,类似于
.robertsProject
(注意圆点更可能是该目录不存在)。 - 将文件夹中的所有文件和目录复制到这个新创建的文件夹中。
- 创建一个
.sh
文件,就像上面的文件一样(请注意,您知道要将文件移动到哪里以及它们的位置,因此您可以在脚本中写入正确的路径)。 - 将
.sh
文件注册到 crontab。
完成!收到该文件的人只需 运行 安装一次此安装程序(您将在 README 中记录如何安装),他们就可以使用您的工具。