-
Notifications
You must be signed in to change notification settings - Fork 80
/
README.Rmd
203 lines (150 loc) · 6.19 KB
/
README.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
---
output: github_document
---
<!-- README.md is generated from README.Rmd. Please edit that file -->
```{r setup, include = FALSE}
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>",
fig.path = "man/figures/README-",
out.width = "100%"
)
if (basename(getwd()) == "docs") {
knitr::opts_knit$set(root.dir = file.path(getwd(), ".."))
}
fs:::pkgdown_tmp(c("/tmp/filedd463d6d7e0f", "/tmp/filedd464dbb3467"))
```
# fs <a href="https://fs.r-lib.org/"><img src="man/figures/logo.png" align="right" height="138" alt="fs website" /></a>
<!-- badges: start -->
[![lifecycle](https://img.shields.io/badge/lifecycle-maturing-blue.svg)](https://lifecycle.r-lib.org/articles/stages.html#maturing)
[![R-CMD-check](https://github.com/r-lib/fs/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/r-lib/fs/actions/workflows/R-CMD-check.yaml)
[![Codecov test coverage](https://codecov.io/gh/r-lib/fs/graph/badge.svg)](https://app.codecov.io/gh/r-lib/fs)
<!-- badges: end -->
**fs** provides a cross-platform, uniform interface to file system operations.
It shares the same back-end component as [nodejs](https://nodejs.org), the
[libuv](https://docs.libuv.org/en/v1.x/fs.html) C library, which brings the
benefit of extensive real-world use and rigorous cross-platform testing. The
name, and some of the interface, is partially inspired by Rust's [fs
module](https://doc.rust-lang.org/std/fs/index.html).
## Installation
You can install the released version of **fs** from [CRAN](https://CRAN.R-project.org) with:
``` r
install.packages("fs")
```
And the development version from [GitHub](https://github.com/) with:
```r
pak::pak("r-lib/fs")
```
## Comparison vs base equivalents
**fs** functions smooth over some of the idiosyncrasies of file handling with
base R functions:
* Vectorization. All **fs** functions are vectorized, accepting multiple paths
as input. Base functions are inconsistently vectorized.
* Predictable return values that always convey a path. All **fs** functions
return a character vector of paths, a named integer or a logical vector, where
the names give the paths. Base return values are more varied: they are often
logical or contain error codes which require downstream processing.
* Explicit failure. If **fs** operations fail, they throw an error. Base
functions tend to generate a warning and a system dependent error code. This
makes it easy to miss a failure.
* UTF-8 all the things. **fs** functions always convert input paths to UTF-8 and
return results as UTF-8. This gives you path encoding consistency across OSes.
Base functions rely on the native system encoding.
* Naming convention. **fs** functions use a consistent naming convention.
Because base R's functions were gradually added over time there are a number
of different conventions used (e.g. `path.expand()` vs `normalizePath()`;
`Sys.chmod()` vs `file.access()`).
### Tidy paths
**fs** functions always return 'tidy' paths. Tidy paths
- Always use `/` to delimit directories
- never have multiple `/` or trailing `/`
Tidy paths are also coloured (if your terminal supports it) based on the
file permissions and file type. This colouring can be customized or extended by
setting the `LS_COLORS` environment variable, in the same output format as [GNU
dircolors](https://www.bigsoft.co.uk/blog/index.php/2008/04/11/configuring-ls_colors).
## Usage
**fs** functions are divided into four main categories:
* `path_` for manipulating and constructing paths
* `file_` for files
* `dir_` for directories
* `link_` for links
Directories and links are special types of files, so `file_` functions
will generally also work when applied to a directory or link.
```{r}
library(fs)
# Construct a path to a file with `path()`
path("foo", "bar", letters[1:3], ext = "txt")
# list files in the current directory
dir_ls()
# create a new directory
tmp <- dir_create(file_temp())
tmp
# create new files in that directory
file_create(path(tmp, "my-file.txt"))
dir_ls(tmp)
# remove files from the directory
file_delete(path(tmp, "my-file.txt"))
dir_ls(tmp)
# remove the directory
dir_delete(tmp)
```
**fs** is designed to work well with the pipe, though because it is a
minimal-dependency infrastructure package it doesn't provide the pipe itself.
You will need to attach [magrittr](https://magrittr.tidyverse.org) or similar.
```{r}
library(magrittr)
paths <- file_temp() %>%
dir_create() %>%
path(letters[1:5]) %>%
file_create()
paths
paths %>% file_delete()
```
**fs** functions also work well in conjunction with other
[tidyverse](https://www.tidyverse.org/) packages, like
[dplyr](https://dplyr.tidyverse.org) and [purrr](https://purrr.tidyverse.org).
Some examples...
```{r}
suppressMessages(
library(tidyverse))
```
Filter files by type, permission and size
```{r}
dir_info("src", recurse = FALSE) %>%
filter(type == "file", permissions == "u+r", size > "10KB") %>%
arrange(desc(size)) %>%
select(path, permissions, size, modification_time)
```
Tabulate and display folder size.
```{r}
dir_info("src", recurse = TRUE) %>%
group_by(directory = path_dir(path)) %>%
tally(wt = size, sort = TRUE)
```
Read a collection of files into one data frame.
`dir_ls()` returns a named vector, so it can be used directly with
`purrr::map_df(.id)`.
```{r}
# Create separate files for each species
iris %>%
split(.$Species) %>%
map(select, -Species) %>%
iwalk(~ write_tsv(.x, paste0(.y, ".tsv")))
# Show the files
iris_files <- dir_ls(glob = "*.tsv")
iris_files
# Read the data into a single table, including the filenames
iris_files %>%
map_df(read_tsv, .id = "file", col_types = cols(), n_max = 2)
file_delete(iris_files)
```
## Feedback wanted!
We hope **fs** is a useful tool for both analysis scripts and packages.
Please open [GitHub issues](https://github.com/r-lib/fs) for any feature requests or bugs.
In particular, we have found non-ASCII filenames in non-English locales on
Windows to be especially tricky to reproduce and handle correctly. Feedback
from users who use commonly have this situation is greatly appreciated.
## Code of Conduct
Please note that the fs project is released with a
[Contributor Code of Conduct](https://fs.r-lib.org/dev/CODE_OF_CONDUCT.html).
By contributing to this project, you agree to abide by its terms.