返回目录中文件的clojure函数

问题描述 投票:1回答:4

我想做一个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))))

这个函数确实列出了所有今天修改过的文件 我现在想做的是把 "文件 "传入一个函数,比如:

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

这样的函数中进行进一步的处理。

我希望能得到一些帮助,我可能监督的东西很简单,却让我烦了几个小时了。我一直在clojure文档和互联网上搜索,然而我没有找出正确的搜索表达式来得到答案。

方向已经足够了,我喜欢学习,而且我对clojure的编程相当陌生。

clojure
4个回答
1
投票

有几件事。

  1. returnfilelist使用 def 内的函数。 def 定义并绑定软件包全局命名空间中的符号,这几乎不是你想要做的。在包的全局命名空间中定义和绑定符号,这几乎不是你想要做的。let 而不是函数本地符号绑定。
  2. returnfilelist 从未实际返回过它所计算的内容。 函数中涉及 doseq 的最后一条语句实际上是返回 nil。 你可能想要返回文件。

下面是经过适当修改的 returnfilelist (我尽可能地保持它与您的原始实现接近,以说明让您的代码工作的关键变化:其他答案使用了 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...
))

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]))))

这将返回一个对的序列,包含匹配的文件作为第一个元素,以及函数的结果 parse-file 不管是什么)作为第二种。

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


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

线程宏(thread-first和thread-last)用于创建管道,在管道中进行一次数据转换,然后传递到下一步。

在函数中应该使用let绑定而不是defs。

函数名应该用破折号来代替通常的空格。 在转换函数中使用->也是很常见的。 例如,date-to-str变成了date->str。


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"))

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

(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
© www.soinside.com 2019 - 2024. All rights reserved.