Jenny Bryan
17 August, 2014
The Linux tree command spits out a plain text listing of a directory.
I've often wanted this in R markdown documents, especially for exposition. While I realize the full-fledged tree command is just a brew install tree away for me ... I want these documents to be easy for my students to compile. I wanted a plain R solution.
The twee() function is a first attempt at this. It's got a whopping two arguments:
paththe directory to list; defaults to working directorylevelhow deep to list; defaults toInf, i.e. as deep as it goes
I create some files, tucked down in subdirectories.
jfile <- "example"
writeLines(c("line 1", "line 2"), jfile)
dir.create("foo/this/is/an", recursive = TRUE)
file.copy(jfile, "foo/this/is/an")
## [1] TRUE
dir.create("foo/this/is/another/super/nested", recursive = TRUE)
file.copy(jfile, "foo/this/is/another/super/nested")
## [1] TRUESource the twee() function! (Source given below and in this Gist file.)
source("twee.R")List the directory foo:
twee("foo")-- this
|__is
|__an
|__example
|__another
|__super
|__nested
|__example
Note: the call twee(), with no arguments at all, will just list current working directory.
Let's clean up.
unlink(c("foo", "example"), recursive = TRUE)Create some more files:
jfile <- "file"
writeLines(c("line 1", "line 2"), jfile)
dir.create("foo/level-01-dir/level-02-dir", recursive = TRUE)
file.copy(jfile, "foo/level-01-file")
## [1] TRUE
file.copy(jfile, "foo/level-01-dir/level-02-file")
## [1] TRUE
file.copy(jfile, "foo/level-01-dir/level-02-dir/level-03-file")
## [1] TRUEList the directory foo with default level = Inf to see all the things:
twee("foo")-- level-01-dir
|__level-02-dir
|__level-03-file
|__level-02-file
-- level-01-file
And again, listing only down to level = 2:
twee("foo", level = 2)-- level-01-dir
|__level-02-dir
|__level-02-file
-- level-01-file
Clean up.
unlink(c("foo", "file"), recursive = TRUE)- validity check of args
- refactor it? the one-line inspiration suggests there are much more clever regexp-y ways to do this ... but that's so hard to read :(
- implement other options of
tree, especially-Fto distinguish, e.g. directories-Pand-Ifor including/excluding based on pattern--filelimit #to cope with directories populated with tons of files
- make my display more similar to that of
treeand friends - output valid Markdown? (I note that
treecan output XML and HTML ... so maybe that's a sign it's time to usetreeitself!)
## quick-and-dirty ersatz Unix tree command in R
## inspired by this one-liner:
## ls -R | grep ":$" | sed -e 's/:$//' -e 's/[^-][^\/]*\//--/g' -e 's/^/ /' -e 's/-/|/'
## found here (among many other places):
## http://serverfault.com/questions/143954/how-to-generate-an-ascii-representation-of-a-unix-file-hierarchy
twee <- function(path = getwd(), level = Inf) {
fad <-
list.files(path = path, recursive = TRUE,no.. = TRUE, include.dirs = TRUE)
fad_split_up <- strsplit(fad, "/")
too_deep <- lapply(fad_split_up, length) > level
fad_split_up[too_deep] <- NULL
jfun <- function(x) {
n <- length(x)
if(n > 1)
x[n - 1] <- "|__"
if(n > 2)
x[1:(n - 2)] <- " "
x <- if(n == 1) c("-- ", x) else c(" ", x)
x
}
fad_subbed_out <- lapply(fad_split_up, jfun)
cat(unlist(lapply(fad_subbed_out, paste, collapse = "")), sep = "\n")
}
This is very useful thank you! We are also trying to get our students to produce such documentation of their projects when they leave, and producing such trees in the description would be very useful. Would you know how to go one step further and produce documented plots such as this?
I have seen them in several presentations on reproducible science and research compendia.
Thanks!
Matthieu