


Download these two R scripts from this workshop’s GitHub repo
https://github.com/jadeynryan/fs-rladies-sl/tree/main
Or, you can copy code chunks from these slides into an R script:
https://jadeyryan.quarto.pub/fs-rladies-sl/
demo/spooky-folder
├── Data
│ ├── ghost-viz.R
│ ├── Pumpkin-Stats.CSV
│ ├── skeletonReport.doc
│ ├── skeletonReport.qmd
│ ├── vampireBATS.txt
│ └── WITCH_list.docx
├── images
│ └── witchCauldron.png
├── Misc Files
│ └── BlackCats.png
├── R
│ ├── ghost data (final) v2.CSV
│ ├── haunted_house.xlsx
│ └── untitled 10 31.R
└── REPORTS
├── ghost data (final).CSV
└── ghost data.csv
Photo by Alpha Perspective on Unsplash
Photo by Sašo Tušar on Unsplash

path_ for manipulating and constructing pathsfile_ for filesdir_ for directorieslink_ for linksPhoto by Reba Spike on Unsplash
| {fs} | Base R |
|---|---|
| Vectorized (accept multiple paths as input) | Inconsistently vectorized |
| Predictable return values that convey a path | Sometimes are logical and sometimes have error codes |
Consistent verb function names (file_exist() and file_show()) |
Different naming conventions (e.g., file.exist() and browseURL()) |
| Throws an error if an operation fails | Sometimes will only generate a warning and OS dependent error code |
{fs} is more consistent and intuitive.
For more details, see Comparison of fs functions, base R, and shell commands article.
library("fs")
# recurse = how many levels of subdirectories to compute on. recurse = TRUE means all of them.
dir_tree(recurse = 2).
├── demo
│ ├── code-from-slides.R
│ ├── generate-spooky-folder.R
│ └── spooky-folder
│ ├── Data
│ ├── images
│ ├── Misc Files
│ ├── R
│ └── REPORTS
├── fs-rladies-sl.Rproj
├── images
│ ├── bulk-density.jpg
│ ├── documents-xkcd.png
│ ├── final-phd-comics.gif
│ ├── mts.jpg
│ ├── mts.webp
│ ├── rangeland.jpg
│ ├── soil-sampling.jpg
│ └── witchy-jr-cat-fs.png
├── README.md
├── slides.html
├── slides.qmd
├── slides.rmarkdown
├── slides.scss
├── slides_files
│ └── libs
│ ├── clipboard
│ ├── quarto-contrib
│ ├── quarto-html
│ └── revealjs
├── _extensions
│ └── quarto-ext
│ ├── fontawesome
│ └── pointer
└── _publish.yml
Construct a path with the right separator
Check if spooky-cat.png exists in the halloween folder
Create a path to an existing image
| Action | Function | Use Case |
|---|---|---|
| Create* | file_create() |
Create a new file |
| Copy* | file_copy() |
Copy a file |
| Move | file_move() |
Move or rename a file |
| Delete* | file_delete() |
Delete a file |
*These also work with dir_ and link_ prefixes
Create root directory
Set up sub-directories
Warning
Must pass vector of names to dir_create. Otherwise, dir_create(root, "R", "data/raw", "data/processed", "output", "reports", "images") will result in this folder path: scary-analysis/R/data/raw/data/processed/output/reports/images/.
Files and directories exist in both locations with dir_copy()
By default, file_copy() will fail if the file already exists.
Error: [EEXIST] Failed to copy 'demo/scary-analysis/R/01-load-data.R' to 'demo/other-scary-analysis/R/01-load-data.R': file already exists
Create a new src folder to move scripts into
R scripts are now only in the src folder after being moved from the R folder
Use file_move() to rename directories and files
file_move(path = "demo/other-scary-analysis/R",
new_path = "demo/other-scary-analysis/src")
dir_tree("demo/other-scary-analysis")demo/other-scary-analysis
├── data
│ ├── processed
│ └── raw
├── images
├── output
├── reports
└── src
├── 01-load-data.R
├── 02-wrangle-data.R
├── 03-model.R
└── 04-visualization.R
Note
If the goal is to rename a folder, don’t use dir_create() first like we did in the last example. Just use file_move() in one step.
Delete the empty R folder from the first move example with dir_delete()
demo/spooky-folder/
├── Data
│ ├── ghost-viz.R
│ ├── Pumpkin-Stats.CSV
│ ├── skeletonReport.doc
│ ├── skeletonReport.qmd
│ ├── vampireBATS.txt
│ └── WITCH_list.docx
├── images
│ └── witchCauldron.png
├── Misc Files
│ └── BlackCats.png
├── R
│ ├── ghost data (final) v2.CSV
│ ├── haunted_house.xlsx
│ └── untitled 10 31.R
└── REPORTS
├── ghost data (final).CSV
└── ghost data.csv
What do you use for folders and files? Is this standardized within just your projects? Team? Organization?
Artwork by Allison Horst
Artwork by Allison Horst
Note
You could just use {stringr} for cleaning, but {janitor} is more comprehensive so you don’t need to write as much regex.
E.g., myImportantFile would be be cleaned to my_important_file.
See the make_clean_names() docs.
Arguments that might come in handy: case, replace, parsing_option, abbreviations, sep_out.
Uh oh – the directory separators and extensions were lost!
demo/spooky-folder/Data
demo/spooky-folder/Data/ghost-viz.R
demo/spooky-folder/Data/Pumpkin-Stats.CSV
demo/spooky-folder/Data/skeletonReport.doc
demo/spooky-folder/Data/skeletonReport.qmd
demo/spooky-folder/Data/vampireBATS.txt
demo/spooky-folder/Data/WITCH_list.docx
demo/spooky-folder/images
demo/spooky-folder/images/witchCauldron.png
demo/spooky-folder/Misc Files
demo/spooky-folder/Misc Files/BlackCats.png
demo/spooky-folder/R
demo/spooky-folder/R/ghost data (final) v2.CSV
demo/spooky-folder/R/haunted_house.xlsx
demo/spooky-folder/R/untitled 10 31.R
demo/spooky-folder/REPORTS
demo/spooky-folder/REPORTS/ghost data (final).CSV
demo/spooky-folder/REPORTS/ghost data.csv
[1] "demo_spooky_folder_data"
[2] "demo_spooky_folder_data_ghost_viz_r"
[3] "demo_spooky_folder_data_pumpkin_stats_csv"
[4] "demo_spooky_folder_data_skeleton_report_doc"
[5] "demo_spooky_folder_data_skeleton_report_qmd"
[6] "demo_spooky_folder_data_vampire_bats_txt"
[7] "demo_spooky_folder_data_witch_list_docx"
[8] "demo_spooky_folder_images"
[9] "demo_spooky_folder_images_witch_cauldron_png"
[10] "demo_spooky_folder_misc_files"
[11] "demo_spooky_folder_misc_files_black_cats_png"
[12] "demo_spooky_folder_r"
[13] "demo_spooky_folder_r_ghost_data_final_v2_csv"
[14] "demo_spooky_folder_r_haunted_house_xlsx"
[15] "demo_spooky_folder_r_untitled_10_31_r"
[16] "demo_spooky_folder_reports"
[17] "demo_spooky_folder_reports_ghost_data_final_csv"
[18] "demo_spooky_folder_reports_ghost_data_csv"
To avoid the separators being turned into underscores, let’s split the directory, name, and extension with path_split()
[[1]]
[1] "demo" "spooky-folder" "Data"
[[2]]
[1] "demo" "spooky-folder" "Data" "ghost-viz.R"
[[3]]
[1] "demo" "spooky-folder" "Data"
[4] "Pumpkin-Stats.CSV"
Clean with {janitor}
Uh oh – the directory separators are maintained, but the extensions are still lost!
demo/spooky-folder/Data
demo/spooky-folder/Data/ghost-viz.R
demo/spooky-folder/Data/Pumpkin-Stats.CSV
demo/spooky-folder/Data/skeletonReport.doc
demo/spooky-folder/Data/skeletonReport.qmd
demo/spooky-folder/Data/vampireBATS.txt
demo/spooky-folder/Data/WITCH_list.docx
demo/spooky-folder/images
demo/spooky-folder/images/witchCauldron.png
demo/spooky-folder/Misc Files
demo/spooky-folder/Misc Files/BlackCats.png
demo/spooky-folder/R
demo/spooky-folder/R/ghost data (final) v2.CSV
demo/spooky-folder/R/haunted_house.xlsx
demo/spooky-folder/R/untitled 10 31.R
demo/spooky-folder/REPORTS
demo/spooky-folder/REPORTS/ghost data (final).CSV
demo/spooky-folder/REPORTS/ghost data.csv
demo/spooky_folder/data
demo/spooky_folder/data/ghost_viz_r
demo/spooky_folder/data/pumpkin_stats_csv
demo/spooky_folder/data/skeleton_report_doc
demo/spooky_folder/data/skeleton_report_qmd
demo/spooky_folder/data/vampire_bats_txt
demo/spooky_folder/data/witch_list_docx
demo/spooky_folder/images
demo/spooky_folder/images/witch_cauldron_png
demo/spooky_folder/misc_files
demo/spooky_folder/misc_files/black_cats_png
demo/spooky_folder/r
demo/spooky_folder/r/ghost_data_final_v2_csv
demo/spooky_folder/r/haunted_house_xlsx
demo/spooky_folder/r/untitled_10_31_r
demo/spooky_folder/reports
demo/spooky_folder/reports/ghost_data_final_csv
demo/spooky_folder/reports/ghost_data_csv
Use path_ext() to get the extensions and {stringr} to replace the underscore before the extension with a period
paths_almost_clean <- paths_clean
# Get extensions
exts <- path_ext(paths) |>
# Remove blanks
stringr::str_subset("\\S") |>
# Remove duplicates
stringr::str_unique() |>
# Make lowercase
stringr::str_to_lower()
# Make dynamic regex pattern including extensions
pattern <- paste0("_(?=(", paste(exts, collapse = "|"), ")$)")
# Replace underscore before ext with period
paths_clean <- stringr::str_replace(paths_almost_clean, pattern, ".") |>
# Make fs_path again
path()Yay! Let’s just re-capitalize the R folder and .R extensions.
demo/spooky_folder/data
demo/spooky_folder/data/ghost_viz_r
demo/spooky_folder/data/pumpkin_stats_csv
demo/spooky_folder/data/skeleton_report_doc
demo/spooky_folder/data/skeleton_report_qmd
demo/spooky_folder/data/vampire_bats_txt
demo/spooky_folder/data/witch_list_docx
demo/spooky_folder/images
demo/spooky_folder/images/witch_cauldron_png
demo/spooky_folder/misc_files
demo/spooky_folder/misc_files/black_cats_png
demo/spooky_folder/r
demo/spooky_folder/r/ghost_data_final_v2_csv
demo/spooky_folder/r/haunted_house_xlsx
demo/spooky_folder/r/untitled_10_31_r
demo/spooky_folder/reports
demo/spooky_folder/reports/ghost_data_final_csv
demo/spooky_folder/reports/ghost_data_csv
demo/spooky_folder/data
demo/spooky_folder/data/ghost_viz.r
demo/spooky_folder/data/pumpkin_stats.csv
demo/spooky_folder/data/skeleton_report.doc
demo/spooky_folder/data/skeleton_report.qmd
demo/spooky_folder/data/vampire_bats.txt
demo/spooky_folder/data/witch_list.docx
demo/spooky_folder/images
demo/spooky_folder/images/witch_cauldron.png
demo/spooky_folder/misc_files
demo/spooky_folder/misc_files/black_cats.png
demo/spooky_folder/r
demo/spooky_folder/r/ghost_data_final_v2.csv
demo/spooky_folder/r/haunted_house.xlsx
demo/spooky_folder/r/untitled_10_31.r
demo/spooky_folder/reports
demo/spooky_folder/reports/ghost_data_final.csv
demo/spooky_folder/reports/ghost_data.csv
paths_clean <- paths_clean |>
# Capitalize R folder name
stringr::str_replace("/r(?=/|$)", "/R") |>
# Capitalize R extension
stringr::str_replace("\\.r", ".R")
# Show the updated files containing R
paths_clean |>
stringr::str_subset("R")[1] "demo/spooky_folder/data/ghost_viz.R"
[2] "demo/spooky_folder/R"
[3] "demo/spooky_folder/R/ghost_data_final_v2.csv"
[4] "demo/spooky_folder/R/haunted_house.xlsx"
[5] "demo/spooky_folder/R/untitled_10_31.R"
But wait… our new folders don’t exist yet!
Error: [ENOENT] Failed to move 'demo/spooky-folder/Data' to 'demo/spooky_folder/data': no such file or directory
Warning
{fs} gotcha! file_move() and file_copy() don’t automatically create parent folders!
Get the parent folders with path_dir()
[1] "demo/spooky_folder" "demo/spooky_folder/data"
[3] "demo/spooky_folder/images" "demo/spooky_folder/misc_files"
[5] "demo/spooky_folder/R" "demo/spooky_folder/reports"
Create the parent folders if they don’t already exist
Filter out folders from current paths and new paths with !is_dir()
demo/spooky_folder
├── data
│ ├── ghost_viz.R
│ ├── pumpkin_stats.csv
│ ├── skeleton_report.doc
│ ├── skeleton_report.qmd
│ ├── vampire_bats.txt
│ └── witch_list.docx
├── images
│ └── witch_cauldron.png
├── misc_files
│ └── black_cats.png
├── R
│ ├── ghost_data_final_v2.csv
│ ├── haunted_house.xlsx
│ └── untitled_10_31.R
└── reports
├── ghost_data.csv
└── ghost_data_final.csv
We have nice, consistent names… but the organization is still very wrong!
Use globs to get files based on extension
data <- dir_ls("demo/spooky_folder", recurse = TRUE, glob = "*.csv|*.xlsx")
images <- dir_ls("demo/spooky_folder", recurse = TRUE, glob = "*.png")
misc_files <- dir_ls("demo/spooky_folder", recurse = TRUE, glob = "*.txt")
r <- dir_ls("demo/spooky_folder", recurse = TRUE, glob = "*.R")
reports <- dir_ls("demo/spooky_folder", recurse = TRUE, glob = "*.doc|*.docx|*.qmd")What we started with
demo/spooky-folder
├── Data
│ ├── ghost-viz.R
│ ├── Pumpkin-Stats.CSV
│ ├── skeletonReport.doc
│ ├── skeletonReport.qmd
│ ├── vampireBATS.txt
│ └── WITCH_list.docx
├── images
│ └── witchCauldron.png
├── Misc Files
│ └── BlackCats.png
├── R
│ ├── ghost data (final) v2.CSV
│ ├── haunted_house.xlsx
│ └── untitled 10 31.R
└── REPORTS
├── ghost data (final).CSV
└── ghost data.csv
Our cleaned folder
demo/spooky_folder
├── data
│ ├── ghost_data.csv
│ ├── ghost_data_final.csv
│ ├── ghost_data_final_v2.csv
│ ├── haunted_house.xlsx
│ └── pumpkin_stats.csv
├── images
│ ├── black_cats.png
│ └── witch_cauldron.png
├── misc_files
│ └── vampire_bats.txt
├── R
│ ├── ghost_viz.R
│ └── untitled_10_31.R
└── reports
├── skeleton_report.doc
├── skeleton_report.qmd
└── witch_list.docx
dir_tree() to inspect structure and naming inconsistenciesdir_create()file_move()dir_tree()clean_paths <- function(folder, recurse = TRUE) {
# Split paths into parts
paths <- dir_ls(folder, recurse = recurse)
parts <- path_split(paths)
# Clean to snake_case
parts_clean <- purrr::map(
parts,
\(part) janitor::make_clean_names(part, case = "snake")
)
# Reconstruct paths
paths_clean <- path_join(parts_clean)
# Get extensions
exts <- path_ext(paths) |>
# Remove blanks
stringr::str_subset("\\S") |>
# Remove duplicates
stringr::str_unique() |>
# Make lowercase
stringr::str_to_lower()
# Make dynamic regex pattern including extensions
pattern <- paste0("_(?=(", paste(exts, collapse = "|"), ")$)")
# Replace underscore before ext with period and make R uppercase
paths_clean <- paths_clean |>
stringr::str_replace(pattern, ".") |>
# Capitalize R folder name
stringr::str_replace("/r(?=/|$)", "/R") |>
# Capitalize R extension
stringr::str_replace("\\.r", ".R") |>
# Make fs_path again
path()
return(paths_clean)
}clean_paths() resultspaths <- dir_ls("demo/spooky-folder", recurse = TRUE)
# Run function
paths_clean <- clean_paths("demo/spooky-folder")
paths_cleandemo/spooky_folder/data
demo/spooky_folder/data/ghost_viz.R
demo/spooky_folder/data/pumpkin_stats.csv
demo/spooky_folder/data/skeleton_report.doc
demo/spooky_folder/data/skeleton_report.qmd
demo/spooky_folder/data/vampire_bats.txt
demo/spooky_folder/data/witch_list.docx
demo/spooky_folder/images
demo/spooky_folder/images/witch_cauldron.png
demo/spooky_folder/misc_files
demo/spooky_folder/misc_files/black_cats.png
demo/spooky_folder/R
demo/spooky_folder/R/ghost_data_final_v2.csv
demo/spooky_folder/R/haunted_house.xlsx
demo/spooky_folder/R/untitled_10_31.R
demo/spooky_folder/reports
demo/spooky_folder/reports/ghost_data_final.csv
demo/spooky_folder/reports/ghost_data.csv
rename_files <- function(old_paths, new_paths) {
# Get parent folders
parents <- unique(path_dir(new_paths))
# Create parent folders
parents |>
purrr::map(\(x) {
if (!dir_exists(x)) {
dir_create(x)
}
})
# Filter out folders from files
old_paths <- subset(old_paths, !is_dir(old_paths))
new_paths <- subset(new_paths, !is_dir(new_paths))
# Rename files
file_move(old_paths, new_paths)
# See results
dir_tree(path_common(new_paths))
}Note
path_common() returns the path common to all the paths passed as input.
rename_files() resultsdemo/spooky_folder
├── data
│ ├── ghost_data.csv
│ ├── ghost_data_final.csv
│ ├── ghost_data_final_v2.csv
│ ├── ghost_viz.R
│ ├── haunted_house.xlsx
│ ├── pumpkin_stats.csv
│ ├── skeleton_report.doc
│ ├── skeleton_report.qmd
│ ├── vampire_bats.txt
│ └── witch_list.docx
├── images
│ ├── black_cats.png
│ └── witch_cauldron.png
├── misc_files
│ ├── black_cats.png
│ └── vampire_bats.txt
├── R
│ ├── ghost_data_final_v2.csv
│ ├── ghost_viz.R
│ ├── haunted_house.xlsx
│ └── untitled_10_31.R
└── reports
├── ghost_data.csv
├── ghost_data_final.csv
├── skeleton_report.doc
├── skeleton_report.qmd
└── witch_list.docx
organize_files <- function(folder) {
# List subdirectories and extensions
data <- dir_ls(folder, recurse = TRUE, glob = "*.csv|*.xlsx")
images <- dir_ls(folder, recurse = TRUE, glob = "*.png")
misc_files <- dir_ls(folder, recurse = TRUE, glob = "*.txt")
r <- dir_ls(folder, recurse = TRUE, glob = "*.R")
reports <- dir_ls(folder, recurse = TRUE, glob = "*.doc|*.docx|*.qmd")
# Move files
file_move(data, path(stringr::str_glue("{folder}/data")))
file_move(images, path(stringr::str_glue("{folder}/images")))
file_move(misc_files, path(stringr::str_glue("{folder}/misc_files")))
file_move(r, path(stringr::str_glue("{folder}/R")))
file_move(reports, path(stringr::str_glue("{folder}/reports")))
# See results
dir_tree(folder)
}organize_files() resultsdemo/spooky_folder
├── data
│ ├── ghost_data.csv
│ ├── ghost_data_final.csv
│ ├── ghost_data_final_v2.csv
│ ├── haunted_house.xlsx
│ └── pumpkin_stats.csv
├── images
│ ├── black_cats.png
│ └── witch_cauldron.png
├── misc_files
│ └── vampire_bats.txt
├── R
│ ├── ghost_viz.R
│ └── untitled_10_31.R
└── reports
├── skeleton_report.doc
├── skeleton_report.qmd
└── witch_list.docx
# Start fresh
source("demo/generate-spooky-folder.R")
# Get paths to clean
paths <- dir_ls("demo/spooky-folder", recurse = TRUE)
# Run function
paths_clean <- clean_paths("demo/spooky-folder")
paths_clean
# Review paths_clean before running the next functions!
rename_files(paths, paths_clean)
organize_files("demo/spooky_folder")Use file_info() to get a tibble
# A tibble: 51 × 18
path type size permissions modification_time user group
<fs::path> <fct> <fs::b> <fs::perms> <dttm> <chr> <chr>
1 …code-from-slides.R file 7.75K rw- 2025-10-29 13:36:14 <NA> <NA>
2 …te-spooky-folder.R file 888 rw- 2025-10-29 14:51:06 <NA> <NA>
3 …her-scary-analysis dire… 0 rw- 2025-10-29 15:43:29 <NA> <NA>
4 …cary-analysis/data dire… 0 rw- 2025-10-29 15:43:28 <NA> <NA>
5 …sis/data/processed dire… 0 rw- 2025-10-29 15:43:28 <NA> <NA>
6 …-analysis/data/raw dire… 0 rw- 2025-10-29 15:43:28 <NA> <NA>
7 …ry-analysis/images dire… 0 rw- 2025-10-29 15:43:28 <NA> <NA>
8 …ry-analysis/output dire… 0 rw- 2025-10-29 15:43:28 <NA> <NA>
9 …y-analysis/reports dire… 0 rw- 2025-10-29 15:43:28 <NA> <NA>
10 …scary-analysis/src dire… 0 rw- 2025-10-29 15:43:28 <NA> <NA>
# ℹ 41 more rows
# ℹ 11 more variables: device_id <dbl>, hard_links <dbl>,
# special_device_id <dbl>, inode <dbl>, block_size <dbl>, blocks <dbl>,
# flags <int>, generation <dbl>, access_time <dttm>, change_time <dttm>,
# birth_time <dttm>
files |>
dplyr::filter(type == "directory" | stringr::str_detect(path, ".R")) |>
dplyr::select(path, type, size, birth_time, modification_time)# A tibble: 40 × 5
path type size birth_time modification_time
<fs::path> <fct> <fs::b> <dttm> <dttm>
1 demo/code-from-slides.R file 7.75K 2025-10-28 15:13:31 2025-10-29 13:36:14
2 …nerate-spooky-folder.R file 888 2025-10-05 19:05:07 2025-10-29 14:51:06
3 …o/other-scary-analysis dire… 0 2025-10-29 15:43:28 2025-10-29 15:43:29
4 …er-scary-analysis/data dire… 0 2025-10-29 15:43:28 2025-10-29 15:43:28
5 …nalysis/data/processed dire… 0 2025-10-29 15:43:28 2025-10-29 15:43:28
6 …cary-analysis/data/raw dire… 0 2025-10-29 15:43:28 2025-10-29 15:43:28
7 …-scary-analysis/images dire… 0 2025-10-29 15:43:28 2025-10-29 15:43:28
8 …-scary-analysis/output dire… 0 2025-10-29 15:43:28 2025-10-29 15:43:28
9 …scary-analysis/reports dire… 0 2025-10-29 15:43:28 2025-10-29 15:43:28
10 …her-scary-analysis/src dire… 0 2025-10-29 15:43:28 2025-10-29 15:43:28
# ℹ 30 more rows
files[
files$type == "directory" | grepl("\\.R$", files$path),
c("path", "type", "size", "birth_time", "modification_time")
]# A tibble: 40 × 5
path type size birth_time modification_time
<fs::path> <fct> <fs::b> <dttm> <dttm>
1 demo/code-from-slides.R file 7.75K 2025-10-28 15:13:31 2025-10-29 13:36:14
2 …nerate-spooky-folder.R file 888 2025-10-05 19:05:07 2025-10-29 14:51:06
3 …o/other-scary-analysis dire… 0 2025-10-29 15:43:28 2025-10-29 15:43:29
4 …er-scary-analysis/data dire… 0 2025-10-29 15:43:28 2025-10-29 15:43:28
5 …nalysis/data/processed dire… 0 2025-10-29 15:43:28 2025-10-29 15:43:28
6 …cary-analysis/data/raw dire… 0 2025-10-29 15:43:28 2025-10-29 15:43:28
7 …-scary-analysis/images dire… 0 2025-10-29 15:43:28 2025-10-29 15:43:28
8 …-scary-analysis/output dire… 0 2025-10-29 15:43:28 2025-10-29 15:43:28
9 …scary-analysis/reports dire… 0 2025-10-29 15:43:28 2025-10-29 15:43:28
10 …her-scary-analysis/src dire… 0 2025-10-29 15:43:28 2025-10-29 15:43:28
# ℹ 30 more rows
Use code snippets in an RStudio project to set up folder scaffolding!
Create new RStudio Project
Go to Tools > Edit Code Snippets... > R
Paste the following (with this exact tabbing):
snippet project
fs::dir_create(
c("data/raw", "data/processed", "images", "R", "reports", "output")
)
project in an R script or in the Console and then press Shift+Tab.Photo by Bee Felten-Leidel on Unsplash
🏡 Home for slides:
jadeyryan.quarto.pub/fs-rladies-sl/
👩🏻💻 Source code:
github.com/jadeynryan/fs-rladies-sl
🎥 Recordings from previous workshops & talks:
links in GitHub repo or my YouTube playlist
