R命令行文件对话框?类似于file.choose

时间:2012-02-03 01:35:38

标签: file r command-line explorer

是否有R用户知道R中的“打开文件”类型的功能? 优选地,它具有文本界面,例如:

> file.choose("/path/to/start/at")
path/to/start/at:
[1] [D] a_directory
[2] [D] another_directory
[3] [F] apicture.tif
[4] [F] atextfile.txt
...
[..] Go up a directory
Enter selection: 

我可以浏览,直到我选择了我想要的文件。

知道当前的file.choose,但是(无论如何在Linux上)只是说“输入文件名:”并接受你输入的任何内容,但不会给你浏览的能力。 (也许在Windows上它会显示一个“打开文件”对话框?)。

我可以使用打开的文件对话框,但是我希望远离为此加载像RGtk2 / tcltk / etc这样的GUI包。

我也可以自己编写上面的文本浏览器,但我想在我尝试重新发明轮子之前,我会问是否有人知道这样的功能(并且在它工作之前很多很多次都弄错了!)

欢呼声。

更新

对于基于文本的界面,答案是“不”。但基于@ TylerRinker的解决方案和@Iterator的评论,我编写了自己的函数来做到这一点(这比我想象的要容易得多!):

修改 - 修改后的默认设置为multiple=F,因为人们通常会选择一个文件。

#' Text-based interactive file selection.
#'@param root the root directory to explore
#'             (default current working directory)
#'@param multiple boolean specifying whether to allow 
#'                 multiple files to be selected
#'@return character vector of selected files.
#'@examples 
#'fileList <- my.file.browse()
my.file.browse <- function (root=getwd(), multiple=F) {
    # .. and list.files(root)
    x <- c( dirname(normalizePath(root)), list.files(root,full.names=T) )
    isdir <- file.info(x)$isdir
    obj <- sort(isdir,index.return=T,decreasing=T)
    isdir <- obj$x
    x <- x[obj$ix]
    lbls <- sprintf('%s%s',basename(x),ifelse(isdir,'/',''))
    lbls[1] <- sprintf('../ (%s)', basename(x[1]))

    files <- c()
    sel = -1
    while ( TRUE ) {
        sel <- menu(lbls,title=sprintf('Select file(s) (0 to quit) in folder %s:',root))
        if (sel == 0 )
            break
        if (isdir[sel]) {
            # directory, browse further
            files <- c(files, my.file.browse( x[sel], multiple ))
            break
        } else {
            # file, add to list
            files <- c(files,x[sel])
            if ( !multiple )
                break
            # remove selected file from choices
            lbls <- lbls[-sel]
            x <- x[-sel]
            isdir <- isdir[-sel]
        }
    }
    return(files)
}

因为我使用normalizePath,所以可能会使用符号链接和'..'进行限制,但是很好。

2 个答案:

答案 0 :(得分:2)

我有一些你想要的东西,我保留在我的.Rprofile中。它有一个菜单界面,因为它是查看工作目录的默认设置。如果你想将它扩展为从根目录开始并使用那里的菜单,你必须做很多修改功能。

该函数仅在菜单中找到.txt .R和.Rnw文件。

Open <- function(method = menu) {
    wd<-getwd()
    on.exit(setwd(wd))

    x <- dir()
    x2 <- subset(x, substring(x, nchar(x) - 1, nchar(x)) == ".R" | 
        substring(x, nchar(x) - 3, nchar(x)) %in%c(".txt", ".Rnw"))

    if (is.numeric(method)) {      
        x4 <- x2[method]
        x5 <- as.character(x4)
        file.edit(x5)
    } else { 
        switch(method, 
            menu = { x3 <- menu(x2)
                     x4 <- x2[x3]
                     x5 <- as.character(x4)
                     file.edit(x5)
                    }, 
            look = file.edit(file.choose()))
    }
}

##########
#Examples
#########
Open()
Open("L")

答案 1 :(得分:1)

这不使用'menu'但我希望能够显示“D”,如果某个东西是目录。它可以通过在字符串的开头添加“D”或者其他东西来修改哦。默认为从当前工作目录开始。有很多可以调整和更强大,但这肯定是一个开始。

## File chooser
file.chooser <- function(start = getwd(), all.files = FALSE){
    DIRCHAR <- "D"
    currentdir <- path.expand(start)
    repeat{
        ## Display the current directory and add .. to go up a folder
        display <- c(dir(currentdir, all.files = all.files))
        ## Find which of these are directories
        dirs <- c(basename(list.dirs(currentdir, rec=F)))

        if(!all.files){
            display <- c("..", display)
            dirs <- c("..", dirs)
        }

        ## Grab where in the vector the directories are
        dirnumbers <- which(display %in% dirs)

        n <- length(display)
        ## Create a matrix to display
        out <- matrix(c(1:n, rep("", n), display), nrow = n)
        ## Make the second column an indicator of whether it's a directory
        out[dirnumbers, 2] <- DIRCHAR
        ## Print - don't use quotes
        print(out, quote = FALSE)
        ## Create choice so that it exists outside the repeat
        choice <- ""
        repeat{
            ## Grab users input
            ## All of this could be made more robust
            choice <- scan(what = character(), nmax = 1, quiet = T)
            ## Q or q will allow you to quit with no input
            if(tolower(choice) == "q"){
                return(NULL)
            }
            ## Check if the input is a number
            k <- suppressWarnings(!is.na(as.numeric(choice)))
            if(k){
                break
            }else{
                ## If the input isn't a number display a message
                cat("Please input either 'q' or a number\n")
            }
        }
        ## Coerce the input string to numeric
        choice <- as.numeric(choice)

        if(out[choice, 2] != DIRCHAR){
            ## If the choice isn't a directory return the path to the file
            return(file.path(currentdir, out[choice, 3]))
        }else{
            ## If the input is a directory add the directory
            ## to the path and start all over
            currentdir <- path.expand(file.path(currentdir, out[choice, 3]))
        }
    }
}

file.chooser()

编辑:我没有看到您的更新。你的功能比我的好多了!你应该发布你的答案并接受它。