2014-11-21 96 views
3

我想用clojure壓縮文件夾遞歸。這種文件夾的一個例子是如何用Clojure遞歸壓縮文件夾

├── a 
├── b 
│   ├── c 
│   │   └── ccc.txt 
│   └── bb.txt 
├── c 
├── a.txt 
└── b.txt 

選項1:使用OS從內的Clojure

什麼與zip在Ubuntu是執行在該結構中的根目錄以下的工作原理:

zip -r result.zip * 

但是你必須在工作目錄中才能做到這一點。使用絕對路徑會產生其他結果,而忽略所有路徑將會使結構趨於平坦。

問題是,你不能改變工作目錄中的Clojure,不是我所知道的是..

選項2:使用本地的Clojure(或Java)

這應該是可能的,我在Clojure或Java包裝中發現了一些zip實現。但其中大多數是單個文件。

這可能是一個解決辦法:http://www.java-forums.org/blogs/java-io/973-how-work-zip-files-java.html

但在此之前我嘗試了這一點,我想現在還是沒有一個很好的Clojure庫周圍。

回答

7

怎麼樣使用這樣的事情clojure.core/file-seq

(require '[clojure.java.io :as io]) 
(import '[java.util.zip ZipEntry ZipOutputStream]) 

(with-open [zip (ZipOutputStream. (io/output-stream "foo.zip"))] 
    (doseq [f (file-seq (io/file "/path/to/directory")) :when (.isFile f)] 
    (.putNextEntry zip (ZipEntry. (.getPath f))) 
    (io/copy f zip) 
    (.closeEntry zip))) 
+0

非常好!我有時間檢查一下,但是如果結果真的肯定會接受。 – Peter 2014-11-21 17:14:44

+0

整潔但不遞歸:) – 2014-11-21 17:20:10

+0

@JamesSharp'file-seq'使用'tree-seq',這是一個深度優先的步行。 – Kyle 2014-11-21 17:26:10

0

檢查https://github.com/AeroNotix/swindonjava.util.zip的一個很好的包裝。使用流https://github.com/chmllr/zeus一個簡單的Clojure庫拉鍊基於壓縮

+0

我有,無論是是一種解決方案 – Peter 2014-11-21 17:04:09

+0

您是否檢查過Raynes測試的壓縮? https://github.com/Raynes/fs/blob/master/test/me/raynes/core_test.clj#L335它可能是遍歷目錄樹並壓縮它的好開始。它也有不同的壓縮算法和體面的文檔http://raynes.github.io/fs/me.raynes.fs.compression.html – 2014-11-21 17:10:03

+0

我知道他的好庫和使用它,但不是爲了壓縮,但我沒有'如果我能夠回憶起來,就可以找到目錄的解決方案,不過謝謝你的提示。 – Peter 2014-11-21 17:16:36

0

基於@Kyle答案:

(require '[clojure.java.io :as io]) 
(import '[java.util.zip ZipEntry ZipOutputStream]) 


(defn zip-folder 
    "p input path, z output zip" 
    [p z] 
    (with-open [zip (ZipOutputStream. (io/output-stream z))] 
    (doseq [f (file-seq (io/file p)) :when (.isFile f)] 
     (.putNextEntry zip (ZipEntry. (str/replace-first (.getPath f) p ""))) 
     (io/copy f zip) 
     (.closeEntry zip))) 
    (io/file z))