【问题标题】:Listing files in a directory in Clojure在 Clojure 的目录中列出文件
【发布时间】:2012-01-23 21:21:56
【问题描述】:

如何从 Clojure 中特定目录中的所有文件创建一个列表?我必须求助于调用 Java 还是 Clojure 可以本地处理?

【问题讨论】:

    标签: java clojure


    【解决方案1】:

    使用file-seq 函数。

    用法示例:

    (def directory (clojure.java.io/file "/path/to/directory"))
    (def files (file-seq directory))
    (take 10 files)
    

    【讨论】:

    • 你有代码示例吗?我很难找到一个,而且你链接到的 API 文档不是很解释。 Clojure 新手在这里。
    • file-seq 本身就是tree-seq 的一个很好的代码示例,可用于访问任何分层数据结构。
    • 请务必查看 file-seq 返回的 docs on the java.io.file 对象。
    • 从技术上讲,OP 并没有说他们想要递归列出的文件,这(连同目录本身)是您将通过file-seq 得到的。如果这不是他们想要的,.listFiles 加上目录检查是更好的选择。
    【解决方案2】:

    Clojure 旨在支持 Java 平台,这是 Clojure 不提供自己的 API 的一个领域。这意味着您可能必须深入研究 Java,但您必须使用的类完全可以直接从 Clojure 中使用。

    您应该在 javadocs 中阅读的一类是java.io.File,它代表一个文件路径

    http://docs.oracle.com/javase/6/docs/api/java/io/File.html

    .listFiles 实例方法返回一个包含File 对象的数组(您可以将其用作序列)——一个对应于File 实例标识的目录中的每个条目。还有其他有用的方法可以确定File 是否存在、是否为目录等等。

    示例

    (ns my-file-utils
      (:import java.io.File))
    
    (defn my-ls [d]
      (println "Files in " (.getName d))
      (doseq [f (.listFiles d)]
        (if (.isDirectory f)
          (print "d ")
          (print "- "))
        (println (.getName f))))
    
    ;; Usage: (my-ls (File. "."))
    

    构造文件对象

    File 的构造函数有时使用起来有点不方便(尤其是在一次合并多个路径段时),在这种情况下,Clojure 提供了一个有用的辅助函数:clojure.java.io/file。作为它的参数,它接受路径段作为字符串或文件。段与平台的正确路径分隔符连接。

    http://clojuredocs.org/clojure_core/clojure.java.io/file

    注意:Clojure 还提供了 file-seq 函数,该函数通过从给定文件开始的文件层次结构返回前序遍历(作为 seq)。

    【讨论】:

      【解决方案3】:

      还可以查看fs library

      如果您只需要目录中的文件列表,则可能不值得引入额外的依赖项,但那里有许多有用的实用功能,例如:

      • 创建目录结构
      • 复制、删除、移动
      • 检查和更改权限
      • 分割和规范化路径
      • 创建临时文件和目录
      • 通配符
      • 使用 zip 和 tar 文件

      【讨论】:

        【解决方案4】:

        通常,当我们说要列出目录时,我们的意思是要获取文件名或路径,所以->

        列出目录的最简单方法:

        (seq (.list (clojure.java.io/file ".")))
        

        如果你想递归列出它,那么:

        (map #(.getPath %)
            (file-seq (clojure.java.io/file ".")))
        

        【讨论】:

        • 我第一次在底部看到最佳答案。另外,我喜欢答案如何解释英文“列出目录”的含义——返回一个列表,而不是文件树。
        • 如果你只想要files,那么可以添加isFile过滤器(->> "./src/dir/of/interest" clojure.java.io/file文件-seq (filter #(.isFile %)) (map #(.getPath %)))
        【解决方案5】:
        (use 'clojure.java.io)
        (-> "/tmp" file .listFiles)
        

        后一个表达式是从方法 listFiles 返回的文件对象数组,调用从路径“/tmp”创建的文件对象。这是一种奇特的写法:

        (.listFiles (file "/tmp"))
        

        【讨论】:

          【解决方案6】:

          要使修改后的代码与原始示例代码的功能相匹配,您应该添加获取文件名的调用,如下所示。

          (def directory (clojure.java.io/file "/path/to/directory"))
          (def files 
              (for [file (file-seq directory)] (.getName file)))
          (take 10 files)
          

          【讨论】:

          • 是的......这绝对是要走的路!
          【解决方案7】:

          一个用于列出目录中文件的宏 - 递归地或仅在父目录中。它还可以搜索具有特定结尾扩展名的文件。

              ;; lists all the files recursively inside the directory passed as d like "."
          (defmacro my-rec-list
            "generate the recursive list" {:added "1.0"}
            [d str rec]
            `(->> ~d
                 clojure.java.io/file
                 ~(if (= rec "rec")
                    `file-seq
                    `(.listFiles)) 
                 ~(cond 
                    (= str "file")  `(filter #(.isFile %))
                    (= str "dir")   `(filter #(.isDirectory %))
                    :always         `(filter #(.matches (.getPathMatcher 
                                    (java.nio.file.FileSystems/getDefault)
                                    ~str) (.getFileName (.toPath %)))))
                 (mapv #(.getAbsolutePath %))))
          
          
          (defn my-rec-ls-file 
            "generate the recursive list for only files in a directory"
            [d ] 
            (my-rec-list d "file" "rec"))
          (defn my-rec-ls-dir 
            "generate the recursive list for only directory"
            [d ] 
            (my-rec-list d "dir" "rec"))
          (defn my-rec-ls-jpg 
            "generate the recursive list for files and directory"
            [d ] 
            (my-rec-list d "glob:*.jpg" "rec"))
          (defn my-ls-file 
            "generate the recursive list for only files in a directory"
            [d ] 
            (my-rec-list d "file" "norec"))
          (defn my-ls-dir 
            "generate the recursive list for only directory"
            [d ] 
            (my-rec-list d "dir" "norec"))
          (defn my-ls-jpg 
            "generate the recursive list for files and directory"
            [d ] 
            (my-rec-list d "glob:*.jpg" "norec"))
          

          它导致了不同的函数,可以用目录调用来获取文件列表、目录或匹配的扩展文件 - 递归或非递归。 例子是 -

          (def directory (clojure.java.io/file "/Path/to/Directory"))
          (my-rec-ls-jpg directory) ;; find all jpg file recessively in directory
          (my-ls-jpg directory) ;; find jpg file in current directory
          

          【讨论】:

            猜你喜欢
            • 2012-12-09
            • 2023-03-03
            • 2012-10-10
            • 2020-01-29
            • 2020-03-19
            • 2013-08-30
            • 2012-03-22
            • 2010-12-04
            • 1970-01-01
            相关资源
            最近更新 更多