Clojure - 是否可以在doseq语句中增加变量?

时间:2014-02-22 23:31:59

标签: clojure

我正在尝试迭代给定目录中的文件列表,并在其名称中添加一个递增变量i = {1,2,3 .....}。

以下是迭代文件并更改每个文件名称的代码:

(defn addCounterToExtIn [d]
  (def i 0)
  (doseq [f (.listFiles (file d)) ] ; make a sequence of all files in d
    (if (and (not (.isDirectory f)) ; if file is not a directry and
             (= '(\. \i \n) (take-last 3 (.getName f))) ) ; if it ends with .in
      (fs/rename f (str d '/ i (.getName f)))))) ; add i to start of its name

我不知道如何将i增加为doseq遍历每个文件。或者,是否有更好的循环用于实现所需的结果?

2 个答案:

答案 0 :(得分:8)

使用file-seqmap-indexed

(require '[clojure.java.io :as io])

(dorun
  (->>
    (file-seq (io/file "/home/eduard/Downloads"))
    (filter #(re-find #".+\.pdf$" (.getName %)))
    (map-indexed (fn [i v] [i v]))))

更改map-indexed中的功能以重命名并完成。 pdf文件的示例输出:

([0 #<File /home/eduard/Downloads/some.pdf>] ...)

答案 1 :(得分:3)

这是我头脑中的第一种方法。这不是理想的,但肯定比问题提出的更惯用。

(def rename-one-file! [file counter]
  (if (and (not (.isDirectory file))
           (= ".in" (str (take-last 3 (.getName file)))))
      (fs/rename file (file (parent dir)
                            (str counter (.getName file)))))


(defn iterate-files-with-counter [fn dir]
  (loop [counter 0
         remaining-files (.listFiles (file dir))]
    (let [current-file (first remaining-files)]
      (fn file counter)
      (recur (+ counter 1) (rest remaining-files))))

(def add-counter-to-ext-in-dir
  (partial iterate-files-with-counter rename-one-file!))

请注意,实际执行重命名的工作与迭代文件的工作分开。拥有大量的小函数比一般的少量大函数更好,并且除非你选择一起使用它们,否则使这些函数可重用/独立甚至比这更好。