List folders/ Files recursively

1,194 views
Skip to first unread message

Abraham

unread,
Oct 6, 2010, 2:49:49 AM10/6/10
to Clojure
Dear All ,

I wanted to list the files of a folder , if a folder within , then it
should list the files of that folder and so on.. ie recursively list
files of folders

I tried with recur & loop and could not do it . Then i searched the
internet for the code , i got the code , but i am not able to
understand it , what is -> for ?
following is the code .


; prints all files
(import 'java.io.File)
(defn walk [dirpath]
(doseq [file (-> dirpath File. file-seq)]
(println (.getPath file) )))


can anybody help to do with using recur / loop so to know how to use
recur or loop.

Thanks in advance
Abraham

B Smith-Mannschott

unread,
Oct 6, 2010, 8:39:58 AM10/6/10
to clo...@googlegroups.com
On Wed, Oct 6, 2010 at 08:49, Abraham <vince...@gmail.com> wrote:
Dear All ,

I wanted to list  the files of a folder , if a folder within , then it
should list the files of that folder and so on.. ie recursively list
files of folders

I tried with recur & loop and could not do it . Then i searched the
internet for the code , i got the code , but i am not able to
understand it , what is -> for ?
following is the code .


-> is a macro. It rewrites the code it's invoked on before it is compiled:

(-> dirpath File. file-seq) 
becomes:
(file-seq (File. dirpath))

You can think of -> threading its first argument through a list of functions. So we give dirpath to File. then we give the result of that to file-seq.
 

; prints all files
(import 'java.io.File)
(defn walk [dirpath]
 (doseq [file (-> dirpath File. file-seq)]
    (println (.getPath file)  )))


This doesn't do what you said you wanted to do above: list all files, recursively. It just lists the files contained directly in dirpath.
 

can anybody help to do with using recur / loop so to know how to use
recur or loop.
 
loop/recur allow one to describe iterative computations in a recursive style. Iterative computations don't consume stack space. 

Listing files recursively is a tree recursion. A tree recursion is not an iterative process. loop/recur won't help you there. You'll need to use real stack-consuming recursion.

Here's an example that will produce a recursive list of all files in or below a given directory:


Note, however, that the recursion is indirect, since walk calls mapcat, which calls walk again.

// Ben


Thanks in advance
Abraham

--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@googlegroups.com
Note that posts from new members are moderated - please be patient with your first post.
To unsubscribe from this group, send email to
clojure+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Abraham

unread,
Oct 6, 2010, 8:55:48 AM10/6/10
to Clojure
Thanks a lot .. really good

On Oct 6, 5:39 pm, B Smith-Mannschott <bsmith.o...@gmail.com> wrote:
> > clojure+u...@googlegroups.com<clojure%2Bunsu...@googlegroups.com >

Justin Kramer

unread,
Oct 6, 2010, 10:59:07 AM10/6/10
to Clojure
On Oct 6, 8:39 am, B Smith-Mannschott <bsmith.o...@gmail.com> wrote:
> On Wed, Oct 6, 2010 at 08:49, Abraham <vincent....@gmail.com> wrote:
> > ; prints all files
> > (import 'java.io.File)
> > (defn walk [dirpath]
> >  (doseq [file (-> dirpath File. file-seq)]
> >     (println (.getPath file)  )))
>
> This doesn't do what you said you wanted to do above: list all files,
> recursively. It just lists the files contained directly in dirpath.

file-seq is based on tree-seq and does indeed return all files and
directories recursively (and lazily).

> Listing files recursively is a tree recursion. A tree recursion is not an
> iterative process. loop/recur won't help you there. You'll need to use real
> stack-consuming recursion.

Just to be a devil's advocate, a tree recursion can be translated to
loop/recur using an explicit stack:

(defn list-files [dirname]
(loop [stack [(java.io.File. dirname)]]
(when-let [f (peek stack)]
(println (.getPath f))
(recur (into (pop stack) (.listFiles f))))))

Changing the stack to a queue would make the traversal happen breadth-
first rather than depth-first.

Justin

Justin Kramer

unread,
Oct 6, 2010, 11:15:45 AM10/6/10
to Clojure
I should mention that Ben's solution is still nice and is basically
how tree-seq is implemented under the hood. It is more idiomatic than
using loop/recur (for most use cases).

Justin

B Smith-Mannschott

unread,
Oct 6, 2010, 1:07:19 PM10/6/10
to clo...@googlegroups.com
On Wed, Oct 6, 2010 at 16:59, Justin Kramer <jkkr...@gmail.com> wrote:
On Oct 6, 8:39 am, B Smith-Mannschott <bsmith.o...@gmail.com> wrote:
> On Wed, Oct 6, 2010 at 08:49, Abraham <vincent....@gmail.com> wrote:
> > ; prints all files
> > (import 'java.io.File)
> > (defn walk [dirpath]
> >  (doseq [file (-> dirpath File. file-seq)]
> >     (println (.getPath file)  )))
>
> This doesn't do what you said you wanted to do above: list all files,
> recursively. It just lists the files contained directly in dirpath.

file-seq is based on tree-seq and does indeed return all files and
directories recursively (and lazily).


Cool! I wasn't familiar with it. I guess I assumed it was something like (seq (.listFiles foo)).
 
> Listing files recursively is a tree recursion. A tree recursion is not an
> iterative process. loop/recur won't help you there. You'll need to use real
> stack-consuming recursion.

Just to be a devil's advocate, a tree recursion can be translated to
loop/recur using an explicit stack:

(defn list-files [dirname]
 (loop [stack [(java.io.File. dirname)]]
   (when-let [f (peek stack)]
     (println (.getPath f))
     (recur (into (pop stack) (.listFiles f))))))

Changing the stack to a queue would make the traversal happen breadth-
first rather than depth-first.

Yup. sure.  
 
Justin
Reply all
Reply to author
Forward
0 new messages