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")
}
Thank you!