특정 디렉토리 밑에 있는 파일 중에서 일정시간이 지난 파일을 삭제하고자 할 때 필요한 스크립트이다. 파일 서버를 관리하다보면, 주기적으로 필요 없는 파일들을 삭제해야 하는데, Unix(Linux) 환경에서는 find, rm 등을 조합하여 사용할 수도 있다. 그런 것이 여의치 않고, 굳이 Groovy 를 이용하려고 할 때, 활용하면 좋겠다.
final DAY_LIMIT = 2 // N일
final TARGET_DIR = "./"

println("[Deleted Files]\n")
new File(TARGET_DIR).eachFileRecurse { file ->
    if( file.file ) {
        def lastModified = new Date(file.lastModified())
        def diffDay = new Date() - lastModified
        if(diffDay > DAY_LIMIT) {
            println(lastModified.format("YYYY-mm-dd") + " : $file")
            file.delete()
        }
    }
}



보통의 반복문에서 중간에 빠져나오려면 break 를 사용하지만, 클로져(반복자)에서 break를 사용하면 에러가 발생한다. 다음 코드를 작성하여 실행해보면, 에러를 확인할 수 있을 것이다.

10.times { item -> 
    println item
    if(item == 6) break
}

이에 대한 대안으로는 Exception 을 사용하면 된다. 이제 다시 Exception 을 이용해서 클로져를 빠져나오는 코드를 보자. 좀 번거롭기는 하지만, 확실하게 break 와 같은 효과를 볼 수 있다.

try {
    10.times { item -> 
        println item
        if(item == 6) throw new Exception("break")
    }
} catch (e) {}


Groovy 에서도 100MB 넘는 파일 중에서 중복된 파일을 찾는 프로그램을 만들어보았다. 모든 언어를 공부하면서 만들어보는 것인데, MD5 Checksum 이 같으면 중복된 파일로 인식하고, 카운트하여 정렬하고 출력하도록 하였다. 파일에 대한 MD5 Checksum 기능이 없어서 직접 구현되었고, 이 부분을 제외하면 Ruby 와 거의 비슷하다.
// -----------------------------------------------------------------------------
// 100MB 이상의 파일중에서 중복된 파일 찾기
// -----------------------------------------------------------------------------
 
import java.security.MessageDigest
 
final TARGET_DIR = "C:\\"
final LIMIT_SIZE = 100000000
 
def md5sum(final file) {
    MessageDigest digest = MessageDigest.getInstance("MD5")
    file.withInputStream() { is ->          
        byte[] buffer = new byte[8192]
        int read = 0
        while( (read = is.read(buffer)) > 0) {
            digest.update(buffer, 0, read);
        }
    }                                                        
    byte[] md5 = digest.digest()
    BigInteger bigInt = new BigInteger(1, md5)
    return bigInt.toString(16).padLeft(32, '0')
}
 
def file_list     = []
def distinct_list = [:]
def startDate = new Date().format('yyyy/MM/dd HH:mm:ss')
 
new File(TARGET_DIR).eachFileRecurse { file -> 
    if( file.size() > LIMIT_SIZE ) {
        def md5 = null
        try {
            md5 = md5sum(file)
        } catch(ex) {
            md5 = null
        }
        if (md5 != null) { 
            if(distinct_list[md5] == null)
                distinct_list[md5] = 1
            else
                distinct_list[md5] += 1
            file_list << (md5+"|"+file)
        }
    }
}
 
distinct_list = distinct_list.sort { a, b -> b.value <=> a.value }
 
distinct_list.each { md5, cnt ->
    if( cnt > 1) {
       println "\n[ $md5 ]"
       file_list.each { file -> 
           def (md5_2, filename) = file.split(/\|/)
           if(md5 == md5_2) { println filename }
       }
    }
}
 
def endDate = new Date().format('yyyy/MM/dd HH:mm:ss')
println "\n\n\n"
println "================================================================================"
println "Start Time : $startDate"
println "End   Time : $endDate"
println "================================================================================"



Groovy에서 md5sum 을 구하려면, Java 의 MessageDigest 모듈을 이용해야 한다. 안타깝게도 file 에 대한 md5 checksum 을 구하는 부분은 구현되어 있지 않기 때문에 별도로 구현해야 한다. 다른 언어에서의 방법과 유사하므로 그리 어렵지는 않다. Java 의 모듈을 그대로 이용해야하기 때문에, 구현은 Java 의 그것과 거의 같다.
import java.security.MessageDigest
 
def md5sum(final file) {
    MessageDigest digest = MessageDigest.getInstance("MD5")
    file.withInputStream() { is ->          
        byte[] buffer = new byte[8192]
        int read = 0
        while( (read = is.read(buffer)) > 0) {
            digest.update(buffer, 0, read);
        }
    }                                                        
    byte[] md5 = digest.digest()
    BigInteger bigInt = new BigInteger(1, md5)
    return bigInt.toString(16).padLeft(32, '0')
}
 
println md5sum(new File("md5sum.groovy"))



+ Recent posts