【问题标题】:R: get list of files but not of directoriesR:获取文件列表但不获取目录
【发布时间】:2014-03-30 21:59:52
【问题描述】:

在 R 中如何获取文件夹中的文件列表,而不是目录?

我尝试过使用 dir()list.files()list.dirs() 和不同的选项, 但它们似乎都不起作用。

【问题讨论】:

    标签: r list file


    【解决方案1】:
    setdiff(list.files(), list.dirs(recursive = FALSE, full.names = FALSE))
    

    会成功的。

    【讨论】:

    • 我认为这个更可取,请参阅我对答案的评论。这种方法对我来说也可能更准确。我有 206 个文件 + 目录,我数了一下,有 51 个是目录。这种方法产生了 155 个文件,应该是完全正确的。另一个有 140 个。也许额外的 15 个是系统文件或其他东西,我不确定,但这个有更容易理解和明确正确的结果。
    • 如果您需要全名,这不起作用,因为 list.dirs 在路径中放置了 2 个斜杠。
    【解决方案2】:

    这是一种可能性:

    all.files <- list.files(rec=F)
    all.files[!file.info(all.files)$isdir]
    

    另一种选择(带有扩展名的文件的模式,当然不是那么通用):

    Sys.glob("*.*")
    

    【讨论】:

    • 谢谢,我认为这是一些内置函数。我对 list.files 函数感到困惑,而不是最佳名称选择。
    • 做得好!我已经搜索了一段时间,并没有在任何地方找到它,尽管它非常明显。谢谢
    • 谢谢你。
    • 这行得通,但在某些情况下可能不是最理想的。我在 OneDrive 上使用了一个链接到 Sharepoint 的目录,而 R 需要下载每个文件作为 file.info 的一部分。如果您有大文件,这可能需要很长时间。
    • 这绝对是 R 令人愤怒的时刻。为什么include.dirs=FALSE 不排除目录????
    【解决方案3】:

    base R 没有直接的方法来做到这一点的事实有点令人震惊。 BASH 没有直接的方式也有点奇怪。

    在我看来,最好的 R 解决方案是简单地诉诸 shell:

    filenames = system('ls -p | grep -v /', intern=T)
    

    解释:

    ls -p     Append "/" to end of directory names
    grep -v   Exclude strings matching "/"
    intern=T  store the output in the variable rather then printing to stdout
    

    【讨论】:

      【解决方案4】:

      另一种选择:

      Filter(function(x) file_test("-f", x), list.files())
      

      如果您想充分利用库 functional 的功能,那么您可以节省一些按键操作:

      Filter(Curry(file_test, "-f"), list.files())
      

      后者将file_test 转换为第一个参数设置为“-f”的函数,这基本上是我们在第一种方法中所做的,但Curry 做得更干净,因为可悲的决定function 关键字这么长(为什么不f(x) {...}???)

      【讨论】:

        【解决方案5】:

        所以,我知道这些都是旧的,并且有一个公认的答案,但我尝试了其中的大多数,但没有一个真正奏效。

        这是我得到的:

        1. 文件夹中所有文件的示例:

          files <- list.files("Training/Out/")
          
        2. 该代码的输出:

          [1] "Filtered"           "Training_Chr01.txt" "Training_Chr02.txt" "Training_Chr03.txt"
          [5] "Training_Chr04.txt" "Training_Chr05.txt" "Training_Chr06.txt" "Training_Chr07.txt"
          [9] "Training_Chr08.txt" "Training_Chr09.txt" "Training_Chr10.txt"
          

        第一个 [1] 是目录

        1. 运行此代码以仅获取文件:

          files <- list.files("Training/Out",recursive = TRUE)
          
        2. 有了这个输出:

          [1] "Training_Chr01.txt" "Training_Chr02.txt" "Training_Chr03.txt" "Training_Chr04.txt"
          [5] "Training_Chr05.txt" "Training_Chr06.txt" "Training_Chr07.txt" "Training_Chr08.txt"
          [9] "Training_Chr09.txt" "Training_Chr10.txt"
          

        这或多或少是为了帮助那些看到这个并且和我一样困惑的人。

        【讨论】:

        • 如果您在“已过滤”中有文件,那么这些文件也会被列出。这可能是也可能不是你想要的。
        【解决方案6】:

        我写了一个小包装函数来解决这个问题:

        list_files <- function(path = ".", pattern = NULL, all.files = FALSE, full.names = TRUE, 
                               recursive = FALSE, ignore.case = FALSE, include.dirs = FALSE, no.. = FALSE, 
                               incl_dirs = FALSE){
          
          #Set incl_dirs = TRUE to revert to default list.files() behavior.
        
          if(path == ".") { path = getwd() }
          
          #Include directories if recursive is set.
          if(incl_dirs & recursive) { include.dirs = TRUE }
          
          #Needs to have full.names = TRUE in order to get full path to pass to dir.exists().
          files <- list.files(path = path, pattern = pattern, all.files = all.files, full.names = TRUE, 
                              recursive = recursive, ignore.case = ignore.case, include.dirs = include.dirs, 
                              no.. = no..)
          
          if(!incl_dirs){
            files <- files[!dir.exists(files)]
          }
          
          if(!full.names){
            return(basename(files))
          } else{
            return(files)
          }
          
        }
        

        使用以下示例目录结构:

        dir_test_lvl0/
        ├── dir_test_lvl1
        │   ├── dir_test_lvl2
        │   │   ├── dir_test_lvl3
        │   │   │   ├── dir_test_lvl4
        │   │   │   └── file_test_lvl4
        │   │   └── file_test_lvl3
        │   └── file_test_lvl2
        └── file_test_lvl1
        

        输出看起来像这样,取决于是否设置了incl_dirsrecursive

        #No directories presented.
        #Recursive.
        list_files("dir_test_lvl0", incl_dirs = FALSE, recursive = TRUE, full.names = FALSE)
        # [1] "file_test_lvl4" "file_test_lvl3" "file_test_lvl2" "file_test_lvl1"
        
        #No directories presented.
        #Non-Recursive.
        list_files("dir_test_lvl0", incl_dirs = FALSE, recursive = FALSE, full.names = FALSE)
        # [1] "file_test_lvl1"
        
        
        #With directories presented (default list.files() behavior).
        #Non-recursive.
        list_files("dir_test_lvl0", incl_dirs = TRUE, recursive = FALSE, full.names = FALSE)
        # [1] "dir_test_lvl1"  "file_test_lvl1"
        
        
        #With directories presented (default list.files() behavior).
        #Recursive.
        list_files("dir_test_lvl0", incl_dirs = TRUE, recursive = TRUE, full.names = FALSE)
        # [1] "dir_test_lvl1"  "dir_test_lvl2"  "dir_test_lvl3"  "dir_test_lvl4"  "file_test_lvl4"
        # [6] "file_test_lvl3" "file_test_lvl2" "file_test_lvl1"
        

        所有其他list.files() 选项都由list_files() 忠实地传递给它。该函数没有外部依赖项(仅限base R)。

        【讨论】:

          【解决方案7】:

          如果您愿意尝试非基础 R 包,请尝试 fs package

          只获取目录中的文件

          fs::dir_ls("dir_path", type = "file")
          

          【讨论】:

            【解决方案8】:

            这是另一种使用正则表达式排除没有“。”的列表的解决方案

            list.files("dir_path",pattern="\\.")

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2015-11-30
              • 2013-06-15
              • 2014-11-13
              • 2010-12-26
              • 1970-01-01
              相关资源
              最近更新 更多