Scala syntax to list files

970 views
Skip to first unread message

Shairon Toledo

unread,
Mar 16, 2012, 3:04:17 PM3/16/12
to scala...@googlegroups.com
Hi guys,

I'm trying figure out an elegant way do list all files recursively using scala syntax( no libs), I ended with the code below 

    def fetchFiles(path:String)(op:File => Unit) = {
      for (file <- new File(path).listFiles if !file.isHidden){
        op(file)
        if (file.isDirectory)
          fetchFiles(file.getAbsolutePath)(op)
      } 
    }


    fetchFiles("/", println)
    
I've tried implement it just using "for", in different ways, no success.  







--
Shairon Toledo
http://hashcode.me

Jesse Eichar

unread,
Mar 16, 2012, 4:03:03 PM3/16/12
to shairon...@gmail.com, scala...@googlegroups.com
Watch out for the null pointer exception caused by listFiles returning null :)

√iktor Ҡlang

unread,
Mar 16, 2012, 4:10:23 PM3/16/12
to shairon...@gmail.com, scala...@googlegroups.com
 def fetchFiles(path:String)(op:File => Unit): Unit =
      for (files <- Option(new File(path).listFiles); file <- files if !file.isHidden){
        op(file)
        if (file.isDirectory)
          fetchFiles(file.getAbsolutePath)(op)
      } 

fetchFile("/")(println)

On Fri, Mar 16, 2012 at 8:04 PM, Shairon Toledo <shairon...@gmail.com> wrote:



--
Viktor Klang

Akka Tech Lead
Typesafe - The software stack for applications that scale

Twitter: @viktorklang

Josh Suereth

unread,
Mar 16, 2012, 4:41:57 PM3/16/12
to √iktor Ҡlang, shairon...@gmail.com, scala...@googlegroups.com

val path = "some file"

// Gives us all directories and files in depth-first-searchy fashion.
object files extends Traversable[File] {
  def foreach[U](f: File => U) = {
     def walk(file: File): Unit = 
        if(f.isDirectory)  {
          f(file)
          for {
            files <- Option(file.listFiles)
            file <- files
          } walk(file)
        } else f(file)
     walk(new File(path))
  }
}

files filter (_.getName == ".txt.") // text files

2012/3/16 √iktor Ҡlang <viktor...@gmail.com>

Brian Schlining

unread,
Mar 16, 2012, 5:09:55 PM3/16/12
to scala...@googlegroups.com

Hi Shairon,
If you're using Java 7 you can do the following:

import java.io._
import java.nio.file._
import java.nio.file.attribute._

def fetchFiles(path: String)(op: File => Unit) {
    Files.walkFileTree((new File(path)).toPath, new SimpleFileVisitor[Path]{
        override def preVisitDirectory(dir: Path, attrs: BasicFileAttributes) = {
            op(dir.toFile)
            FileVisitResult.CONTINUE
        }
        override def visitFile(file: Path, attrs: BasicFileAttributes): FileVisitResult = {
            op(file.toFile)
            FileVisitResult.CONTINUE
        }
    })
}


fetchFiles("/") { println }

Daniel Sobral

unread,
Mar 16, 2012, 9:15:37 PM3/16/12
to Josh Suereth, √iktor Ҡlang, shairon...@gmail.com, scala...@googlegroups.com
You really ought to write some Traversable collections, y'know?

2012/3/16 Josh Suereth <joshua....@gmail.com>:

--
Daniel C. Sobral

I travel to the future all the time.

Josh Suereth

unread,
Mar 17, 2012, 5:20:27 AM3/17/12
to Daniel Sobral, √iktor Ҡlang, shairon...@gmail.com, scala...@googlegroups.com

You should see my code...

Shairon Toledo

unread,
Mar 17, 2012, 10:02:44 AM3/17/12
to Josh Suereth, Daniel Sobral, √iktor Ҡlang, scala...@googlegroups.com
Nice code Josh, I understand by eye your strategy, however it didn't run here, I get 

value isDirectory is not a member of java.io.File => U
        if(f.isDirectory)  {

neither inside of object Main{} nor in scala console.

And another question, look in highlights 

 object files extends Traversable[File] {
   def foreach[U](f: File => U) = {
      def walk(file: File): Unit =
         if(f.isDirectory)  {
           f(file)
           for {
             files <- Option(file.listFiles)
             file <- files
           } walk(file)
         } else f(file)
      walk(new File(path))
   }
}

newbie mode: In that context, I didn't get which "files" (green or red) is the reference for the object files and what's return of Option evaluation. Could you clarify? I accept RTFM as answer :)

√iktor Ҡlang

unread,
Mar 17, 2012, 10:06:11 AM3/17/12
to shairon...@gmail.com, Josh Suereth, Daniel Sobral, scala...@googlegroups.com
On Sat, Mar 17, 2012 at 3:02 PM, Shairon Toledo <shairon...@gmail.com> wrote:
Nice code Josh, I understand by eye your strategy, however it didn't run here, I get 

value isDirectory is not a member of java.io.File => U
        if(f.isDirectory)  {

That should be: if (file.isDirectory) {

Josh Suereth

unread,
Mar 17, 2012, 10:06:29 AM3/17/12
to shairon...@gmail.com, Daniel Sobral, √iktor Ҡlang, scala...@googlegroups.com
I'm running into naming conflics here.  Let's try again:

 object files extends Traversable[File] {
   def foreach[U](f: File => U) = {
      def walk(file: File): Unit =
         if(file.isDirectory)  {
           f(file)
           for {
             nextfiles <- Option(file.listFiles)
             nextfile <- nextfiles
           } walk(nextfile)
         } else f(file)
      walk(new File(path))
   }
}

Note:  That version of foreach has stack issues.  I'm mostly trying to show you how creating a *collection* of files can be really simple.  You can make your own "files" collection for different traversal strategies (depth-first, breadth-first) etc.   Dealing with a collection of files should give you access to all the fun powers of collections in Scala, like map/flatMap/filter/groupBy etc.

So, hopefully, I showed you enough of walk to get the gist and write your own custom versions.  In my experience, breadth-first search is *usually* a better option for these file traversables.

Hope that helps!
- Josh

Shairon Toledo

unread,
Mar 17, 2012, 10:17:50 AM3/17/12
to Josh Suereth, Daniel Sobral, √iktor Ҡlang, scala...@googlegroups.com
Yeap indeed I'm from ruby world, Traversable is similar to Enumerator mix-in.
Thx.
Reply all
Reply to author
Forward
0 new messages