'Initialise output location outside of rmarkdown::render
Mikko Marttila helped me to find a way to dynamically timestamp files, using the working code below:
---
title: "Untitled"
author: "Jane Doe"
date: "`r Sys.Date()`"
output: word_document
knit: >
(function(input_file, encoding) {
# Render, keeping intermediate files for extracting front matter
md_dir <- tempdir()
output_file_temp <- rmarkdown::render(
input = input_file,
output_file = tempfile(),
intermediates_dir = md_dir,
clean = FALSE
)
# Get the rendered front matter from the intermediate Markdown file
md_file <- fs::path_ext_set(fs::path_file(input_file), ".knit.md")
metadata <- rmarkdown::yaml_front_matter(fs::path(md_dir, md_file))
# Build the output file name based on rendered metadata
output_name <- with(metadata, paste(title, "by", author, "on", date))
# Add the file extension and move to the working directory
output_ext <- fs::path_ext(output_file_temp)
output_file <- fs::path_ext_set(output_name, output_ext)
fs::file_move(output_file_temp, output_file)
message("Output moved to: ", output_file)
})
---
I would however additionally like to specify the output location from within the knitr
code, based on the projectmanager
and project
. The folder should be created if it does not yet exist.
This could be done as follows: link. I have tried to combine these solutions.
I have tried to do this as in a couple of different ways, but somehow I can't get it to work.
Desired output location:
.../projectname/project")
I tried using setwd
as well as using file.path
:
---
title: "Untitled"
author: "Jane Doe"
date: "`r Sys.Date()`"
output: word_document
projectmanager: "Earth Worm Jim"
project: "getstuffdone"
knit: >
(function(input_file, encoding) {
# Render, keeping intermediate files for extracting front matter
md_dir <- tempdir()
output_file_temp <- rmarkdown::render(
input = input_file,
output_file = tempfile(),
intermediates_dir = md_dir,
clean = FALSE
)
# Get the rendered front matter from the intermediate Markdown file
md_file <- fs::path_ext_set(fs::path_file(input_file), ".knit.md")
metadata <- rmarkdown::yaml_front_matter(fs::path(md_dir, md_file))
# Tom: Specify the main directory in which to store all folders
main_directory <- "Z:/Coding/R_scripts/Markdown/RMarkdown_out/"
# Check current working directory
print(getwd())
# print(metadata)
# Dynamically create a full path for the new file based on projectmanager and project
out_dir <- with(metadata, paste0(main_directory, projectmanager, "/", project, "/"))
print(out_dir)
# Here I tried to set the working directory to the dynamically created wd
setwd(out_dir)
print(getwd())
# Build output file name based on rendered metadata
output_name <- with(metadata, paste(title, date, initials))
print(output_name)
output_dir = file.path(dirname(output_name), out_dir)
print(output_dir)
# path_ext() returns the last extension (if any) for a path
output_ext <- fs::path_ext(output_file_temp)
print(output_ext)
# replaces the extension with a new extension path_ext_set(path, ext)
output_file <- fs::path_ext_set(output_name, output_ext)
print(output_file)
fs::file_move(output_file_temp, output_file)
message("Output file: ", output_file)
})
---
Solution 1:[1]
You're on the right track, but you need to also add a step to create the output directory if needed, and remember to use the created directory when moving the rendered file.
I would steer clear from changing the working directory in a script. Working with the full paths directly tends to lead to easier to understand code.
Here's a modified version with the missing steps added:
---
title: "Untitled"
author: "Jane Doe"
date: "`r Sys.Date()`"
output: word_document
projectmanager: "Earth Worm Jim"
project: "getstuffdone"
knit: >
(function(input_file, encoding) {
# Render, keeping intermediate files for extracting front matter
md_dir <- tempdir()
rendered_file <- rmarkdown::render(
input = input_file,
output_file = tempfile(),
intermediates_dir = md_dir,
clean = FALSE
)
# Get the rendered front matter from the intermediate Markdown file
md_file <- fs::path_ext_set(fs::path_file(input_file), ".knit.md")
metadata <- rmarkdown::yaml_front_matter(fs::path(md_dir, md_file))
# Directory that the output is relative to. Can be an absolute path.
OUTPUT_ROOT <- "."
# Build the output file name and directory based on rendered metadata
output_dir <- with(metadata, fs::path(projectmanager, project))
output_name <- with(metadata, paste(title, "by", author, "on", date))
# Add the file extension
output_ext <- fs::path_ext(rendered_file)
output_file <- fs::path_ext_set(output_name, output_ext)
# Combine parts to final path
output_path <- fs::path(OUTPUT_ROOT, output_dir, output_file)
# Create output directory if it doesn't exist
output_path_dir <- fs::path_dir(output_path)
if (!fs::dir_exists(output_path_dir)) {
fs::dir_create(output_path_dir)
}
# Move render result to output location
fs::file_move(rendered_file, output_path)
message("Output moved to: ", output_path)
})
---
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Mikko Marttila |