scalaで、ソースファイルの行数とか分析するscript

仕事で直接使わなくても、こんな感じでちょっとしたscriptつくって仕事に役立てようぜ( ̄ー ̄)/
ていうか、今まさに仕事で書いたソースファイルの行数数えたくなったので書いたやつです♪*1

REPLに貼りつければ実行できるよ。fileSearchの引数のpathとかエンコードは適当に変えてください

さらに追記 : 最初に上げたやつ行数でなく、byte数文字数計算してましたすいません(T_T)

import java.io.File
type files = List[File]

/**
 * @param f 基準となるディレクトリ
 * @param filterFunc filterとなる関数
 */
def fileSearch(f:File , filterFunc:(File => Boolean) = {_ => true }):files = {
  
  @annotation.tailrec
  def sub(fs:files,result:files):files = {

    if( fs.forall(_.isFile )){
      result:::fs
    }else{
      sub( 
        fs.filter( _.isDirectory ).flatMap( _.listFiles ) ,
        fs.filter{ f => f.isFile & filterFunc( f ) }:::result 
      )
    }
  }
    
  sub( List(f) , Nil )
  
}

//ファイル名が、"scala" で終わるものの一覧取得
val files = fileSearch(new File("""C:\netBeansProject"""), _.getName.endsWith("scala"))

//List[Tuple2(ファイル名,ファイルの行数)] を作成
val nameAndLineCount = files.map{ f => ( f.getName , io.Source.fromFile( f ,"UTF-8" ).getLines.size ) }

//全部プリント
nameAndLineCount foreach println

val sum = nameAndLineCount.foldLeft(0){ case (sum,( _ , count)) => sum + count }

println(
  "\n ファイル数 = " + nameAndLineCount.size + 
  "\n 合計行数 = " + sum + 
  "\n 1ファイル当たりの平均行数 = " + (sum / nameAndLineCount.size)
)

追記

このままだと、テストコードが入っちゃったので、以下のように改造

//ファイル名が、"scala" で終わるもので、"Spec"が入ってないやつの一覧取得
val files = 
  fileSearch(
    new File("""C:\netBeansProject"""), 
    { f => f.getName.endsWith("scala") && ( ! f.getName.contains("Spec") ) }
  )

*1:まえにほぼ同じような物つくったのに、家のパソコンに入ってて、手元に無いっていうorz