'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 |
