---
title: "Filesystems &<br/> Denny's + LQ scraping"
subtitle: "Lecture 14"
author: "Dr. Colin Rundel"
footer: "Sta 523 - Fall 2023"
format:
  revealjs:
    theme: slides.scss
    transition: fade
    slide-number: true
    self-contained: true
execute: 
  echo: true
---

```{r setup}
#| message: False
#| warning: False
#| include: False
options(
  width=80
)

knitr::opts_chunk$set(
  fig.align = "center", fig.retina = 2, dpi = 150,
  out.width = "100%"
)

library(rvest)
```


## Filesystems

Pretty much all commonly used operating systems make use of a hierarchically structured filesystem.

This paradigm consists of directories which can contain files and other directories (which can then contain other files and directories and so on). 

![](imgs/automate_file_path.jpg){fig-align="center" width="25%"}


::: {.aside}
From [Chp 9](https://automatetheboringstuff.com/2e/chapter9/) of Automate the Boring Stuff with Python
:::




## Absolute vs relative paths

Paths can either be absolute or relative, and the difference is very important. For portability reasons you should almost never use absolute paths.

<br/>

#### Absolute path examples

```shell
/var/ftp/pub
/etc/samba.smb.conf
/boot/grub/grub.conf
```

<br/>

#### Relative path examples

```shell
Sta523/filesystem/
data/access.log
filesystem/nelle/pizza.cfg
```


## Special directories

```{r}
dir(path = "data/")
```

. . .

```{r}
dir(path = "data/", all.files = TRUE)
```

::: {.aside}
Files and directorie starting with `.` are hidden by default, in the terminal use `ls -a`
:::

##

```{r}
dir(path = "../")
dir(path = "data/../../")
dir(path = "../../")
```


## Home directory and `~`

Tilde (`~`) is a shortcut that expands to the name of your home directory on unix-like systems.

```{r}
dir(path = "~/")
```

If you append a user's login to `~`, it then refers to that user's home directory (e.g. `~cr173`).

## Why `~`?

Below is the keyboard from an [ADM-3A](https://en.wikipedia.org/wiki/ADM-3A) terminal from the 1970s,

![](imgs/ADM3A.jpg){fig-align="center"}

::: {.aside}
See ["Stop Writing Dead Programs" by Jack Rusher (Strange Loop 2022)](https://www.youtube.com/watch?v=8Ab3ArE8W3s)
:::


## Working directories

R (and OSes) have the concept of a working directory, this is the directory where a program / script is being executed and determines the absolute path of any relative paths used.

```{r}
getwd()
```

. . .

```{r}
setwd("~/")
getwd()
```

##

![](imgs/jenny_fire.png){fig-align="center" width="66%"}

<br/>

::: {.aside}
Source: Jenny Bryan's [Zen and the Art of Workflow Maintenance](https://speakerdeck.com/jennybc/zen-and-the-art-of-workflow-maintenance)
:::



## RStudio and Working Directories

Just like R, RStudio also makes use of a working directory for each of your sessions -  we haven't had to discuss these yet because when you use an RStudio project, the working directory is automatically set to the directory containing the `Rproj` file.

. . .

This makes your project portable as all you need to do is to send the project folder to a collaborator (or push to GitHub) and they can open the project file and have identical *relative* path structure.


## `here`

Thus far we've dealt with mostly simple project organizational structures - all the code has lived in the root directory and sometimes we've had a separate `data` directory for other files. As organization gets more complex to known what the working directory will be for a given script or RMarkdown document.

. . .

`here` is a package that tries to simplify this process by identifying the root of your project for you using simple heuristics and then providing relative paths from that root directory to everything else in your project.

```{r}
here::here()
```

. . .

```{r}
here::here("data/")
```

. . .

```{r}
here::here("../../data/")
```


## Rules of `here::here()`

::: {.small}
> The project root is established with a call to `here::i_am()`. Although not recommended, it can be changed by calling `here::i_am()` again.
>
> In the absence of such a call (e.g. for a new project), starting with the current working directory during package load time, the directory hierarchy is walked upwards until a directory with at least one of the following conditions is found:
>
> - contains a file .here
> 
> - ***contains a file matching [.]Rproj$ with contents matching ^Version: in the first line***
> 
> - contains a file DESCRIPTION with contents matching ^Package:
> 
> - contains a file remake.yml
> 
> - contains a file .projectile
> 
> - contains a directory .git
> 
> - contains a file .git with contents matching ^gitdir:
> 
> - contains a directory .svn
> 
> In either case, here() appends its arguments as path components to the root directory.
:::

## Other useful filesystem functions

- `dir()` - list the contents of a directory

- `basename()` - Removes all of the path up to and include the last path separator (`/`)

- `dirname()` - Returns the path up to but excluding the last path separator 

- `file.path()` - a useful alternative to `paste0()` when combining paths (and urls) as it will add a `/` when necessary.

- `unlink()` - delete files and or directories

- `dir.create()` - create directories

- `fs` package - collection of filesystem related tools based on unix cli tools (e.g. `ls`)


# Denny's and LQ Scraping <br/> Demo
