【问题标题】:R command-line file dialog? similar to file.chooseR命令行文件对话框?类似于 file.choose
【发布时间】:2012-02-25 17:07:48
【问题描述】:

是否有任何 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 的cmets,我编写了自己的函数来完成它(感谢他们,这比我想象的要容易得多!):

编辑 - 修改默认为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,所以它可能会与符号链接和“..”相混淆,.. 但是哦。

【问题讨论】:

  • 在 Windows 和 Mac 上,它确实提供了您所询问的 GUI 类型浏览器。我记得第一次在 Linux 上使用 file.choose...我认为它没用,想要某种浏览器!
  • 我个人不介意 file.choose,但我将此代码提供给一些合作者,他们输入的路径很容易出现拼写错误,所以我只是想要一些只会让他们选择现有文件。
  • 结合shell.exec(我大部分时间都是windows用户;所以不确定其他操作系统上的等效命令是什么)非常好。感谢分享数学咖啡。 shell.exec(my.file.browse())shell.exec(my.file.browse(root = path.expand("~")))

标签: file r command-line explorer


【解决方案1】:

我有一些你想做的东西,我保存在我的 .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")

【讨论】:

  • 干杯 - 我正在考虑编写一个类似的函数,但我会等着看是否有人已经知道一个 - 这将是递归事物中的痛苦编程(探索子文件夹等) .不错的sn-p!
  • @mathematical.coffee 也许我昏昏沉沉,但我不太明白你所说的递归是必要的。正如我所看到的,您有一个状态并期望一个选择,它打开一个编辑器,或者一个 while 循环,它只是更新一个状态(即目录和列表),直到做出选择或退出。
  • 啊@TylerRinker,非常感谢您将我指向menu 函数!我一直在手动执行此操作..!
  • 我设法将您的代码用作文件浏览器功能的基础,多亏了你们两个,结果比我想象的要容易得多。谢谢!
【解决方案2】:

这不使用“菜单”,但如果某物是目录,我希望能够显示“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()

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

【讨论】:

  • 谢谢@Dason!我最终为这个编写了自己的函数,它几乎和你的一样:PI 只是使用menu 来做选择部分,所以我不必自己验证数字输入(我做了“修改和将 D 添加到字符串的开头")。对不起,我不能选择这两个作为答案,但非常感谢你:)
  • @mathematical.coffee 不用担心!我写得很开心。我在提交后立即编辑了一些内容,并意识到您已经编写了自己的函数。你的演讲看起来比我的好,泰勒给了你一个开始,所以我明白了!当我尝试你的功能时,多重选项让我陷入了一个循环,因为我认为当我最终选择一个文件时我做错了。虽然允许选择多个文件,但这是一个有趣的想法。您认为默认值应该是 multiple=T 吗?在我看来,我们只想选择一个文件。
  • 是的,默认值可能应该是 multiple=F - 只是我的一个项目需要这个函数,在这个项目中我们总是需要选择多个文件。
猜你喜欢
  • 2013-04-20
  • 1970-01-01
  • 1970-01-01
  • 2012-01-30
  • 2010-10-07
  • 1970-01-01
  • 2012-06-16
  • 1970-01-01
  • 2012-11-22
相关资源
最近更新 更多