clojure函数返回目录中的文件

时间:2014-09-13 14:04:44

标签: clojure

我正在尝试创建一个clojure函数,该函数返回今天更改的目录中的文件。 它的功能部分=>给我今天更改的所有文件,遍历文件并查找特定值。列出文件和带有值的行。

我得到了解析部分+列出行/文件以及“更改过的文件”,但是我很难合并这两个文件。

到目前为止我设计的用于查找已更改文件的函数是:

(defn returnfilelist
"returns all the files changed today in a directory"
[d]
(def dir (io/file d))
  (def files (for [file (file-seq dir) :when (= (datetostr (Date.(.lastModified file))) (datetostr (new Date))) ](str file  )))
(doseq [f files] (println f) )) ;; <==== this indeed shows the files changed today...

我创建了datetostr函数来进行日期的实际比较:

(defn datetostr [date]
 (str (.format (java.text.SimpleDateFormat. "yyyyMMdd")(.getTime date))))

此功能确实列出了今天更改的所有文件。 我现在想做的是通过“文件”#39;进入类似的功能:

(defn readdir [d]
 (ff/returnfilelist d)) ;; more to add...

进一步处理。

我很欣赏这方面的一些帮助,我可能会监督一些简单的事情但它现在让我烦恼了几个小时。我一直在搜索文件和互联网上,但我没有找到正确的搜索表达式来获得答案。

方向已经足够,我喜欢学习,而且我对编程clojure还不错。

4 个答案:

答案 0 :(得分:1)

一些事情:

  1. returnfilelist在函数内部使用defdef定义并绑定包的全局命名空间中的符号,这几乎不是您想要做的。使用let代替函数本地符号绑定。
  2. returnfilelist永远不会实际返回它计算的内容。函数中的最后一个语句,涉及doseq,实际上返回nil。您可能希望返回文件。
  3. 以下是返回文件列表,其中包含相应的更改(我已将其保持尽可能接近原始实现,以说明使代码正常工作的关键更改:使用filter的其他答案更为惯用,并且应该是首选的):

    (defn returnfilelist
      "returns all the files changed today in a directory"
      [d]
      (let [dir (io/file d)
            files (for [file (file-seq dir) 
                        :when (= (datetostr (Date.(.lastModified file))) 
                                 (datetostr (new Date)))]
                    (str file))]
        (doseq [f files] (println f)) ;; leaving this in for debugging
        files)) ;; <--- the actual return value
    

    ...和readdir成为:

    (defn readdir [d]
      (let [todays-files (ff/returnfilelist d)] 
      ;; more to add...
    ))
    

答案 1 :(得分:0)

要从函数返回一个值,必须由最后执行的语句生成。在您的情况下,您不会返回任何内容,而是在全局范围内定义新值(这本身就是不好的做法);您应该使用let作为本地值:

(defn files-modified-today
  [path]
  (let [dir (io/file dir)]
    (filter modified-today? (file-seq dir))))

(根据自己的喜好实施modified-today?,例如您使用datetostr在问题中所做的那样。)

由于for形式是函数中执行的最后一个语句,因此它的结果将用作函数的返回值,可以在其他地方使用:

(defn read-dir
  [path]
  (for [f (files-modified-today path)]
    (let [result (parse-file f)]
      [f result]))))

这将返回一对seq,包含匹配的文件作为第一个元素,结果parse-file(无论可能是什么)作为第二个。

我希望我没有完全错过你的问题。

答案 2 :(得分:0)

你的问题有点模糊。而且,你写的代码似乎远非惯用。我已经重写了下面的一些函数,向您介绍一些常见的clojure习语。

(import 'java.util.Date)

(defn date->str [date]
  (-> (java.text.SimpleDateFormat. "yyyyMMdd")              ;thread-first macro
      (.format (.getTime date))
      str))

(defn todays-files [dir]
  "returns all the files changed today in a directory"
  (let [today (new Date)]                                   ;let bindings
    (->> (file-seq (clojure.java.io/file dir))              ;thread-last macro.
         (filter #(= (date->str (Date. (.lastModified %))) (date->str today)))
         (map str))))

线程宏(线程优先和线程最后)用于创建执行单个数据转换的管道,然后传递给下一步。

应该使用绑定代替函数内的defs。

函数名称应该包含空格通常所在的破折号。使用 - &gt;也很常见。用于转换功能。例如,date-to-str变为date-&gt; str。

答案 3 :(得分:0)

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

;; 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