Диалоговое окно файла командной строки?похож на file.choose - PullRequest
4 голосов
/ 03 февраля 2012

Есть ли пользователи R, знающие о функции типа "открыть файл" в R? Предпочтительно, чтобы он имел текстовый интерфейс, например ::1001

> 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 отображается диалоговое окно «Открыть файл»?).

Я поддаюсь диалогу с открытым файлом, но предпочитаю держаться подальше от загрузки пакета GUI, такого как RGtk2 / tcltk / etc, только для этого.

Я мог бы также написать вышеупомянутый текстовый браузер сам, но я решил спросить, знает ли кто-нибудь о такой функции, прежде чем я попытаюсь изобрести колесо (и ошибаюсь много, много раз, прежде чем оно заработает!)

веселит.

Обновление

Ответ «нет» текстовому интерфейсу. Но основываясь на решении @ 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 ]

2 голосов
/ 03 февраля 2012

Я сделал то, что вы хотите, и храню в своем профиле. Он имеет интерфейс меню по умолчанию для просмотра рабочего каталога. Если вы хотите, чтобы он был расширен, чтобы начать с корневого каталога и работать с меню оттуда, вам придется многое изменить в функции.

Функция находит в меню только файлы .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 голос
/ 03 февраля 2012

Это не использует «меню», но я хотел иметь возможность отображать «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()

Редактировать: я не видел ваше обновление. Ваша функция немного лучше, чем у меня! Вы должны опубликовать свой ответ и принять его.

...