사용자 도구

사이트 도구


gradle:files

Gradle 파일 다루기

파일 객체 확보

  • Project.file() 메소드로 프로젝트에 상대적인 경로에 있는 파일 객체를 얻을 수 있다.
    // 프로젝트 디렉토리에 대해 상대 경로
    File configFile = file('src/config.xml')
     
    // 절대 경로
    configFile = file(configFile.absoluteFile)
     
    // 현재 명령이 실행된 위치의 상대 경로로 된 파일 객체 사용
    configFile = file(new File('src/config.xml'))
  • file() 메소드에 인자로 아무것이나 넘겨도 되며, 자동으로 이를 File 객체로 바꾸는 시도를 한다. 보통은 String, File 객체를 사용한다.
  • 보통은 프로젝트경로에 상대 경로로 지정되며, 절대 경로 문자열이 넘어올 경우이면 절대 경로를 사용한다.
  • file() 메소드는 file:/some/path.xml같은 URL도 인식한다.
  • file('상대경로') : 현재 디렉토리와 무관하게 프로젝트 디렉토리에 상대 경로로 간주.
  • new File('경로') : 현재 디렉토리에 상대 경로
  • file() 메소드로 절대 경로를 가리키려면 file(new File('경로').absoluteFile) 형태를 사용해야 한다.

File Collections

  • FileCollection Interface. 말 그대로 파일들의 컬렉션이다.
  • Project.files() 메소드로 파일 컬렉션 인스턴스를 생성할 수 있다.
  • file()처럼 프로젝트에 상대적인 경로 우선이다.
  • 일반 용법
    FileCollection collection = files('src/file1.txt', new File('src/file2.txt'), ['src/file3.txt', 'src/file4.txt'])
  • 다양한 용법
    // 일반 컬렉션 처럼 반복 가능
    collection.each {File file ->
        println file.name
    }
     
    // 다른 컬렉션으로 변경
    Set set = collection.files
    Set set2 = collection as Set
    List list = collection as List
    String path = collection.asPath
    File file = collection.singleFile
    File file2 = collection as File
     
    // 컬렉션 합치기, 빼기
    def union = collection + files('src/file3.txt')
    def different = collection - files('src/file3.txt')
  • files()에 클로저 혹은 Callable 인스턴스를 인자로 주기. 클로저에서 files() 메소드의 인자가 될 수 있는 값을 리턴해주면 된다.
    task list << {
        File srcDir
     
        // 클로저로 파일 컬렉션 생성하기. 현재 시점에 srcDir == null 이지만, 늦은 초기화를 하기 때문에 문제가 없다.
        def collection = files { println ">> ${srcDir}"; srcDir.listFiles() }
     
        srcDir = file('src')
        println "Contents of $srcDir.name"
     
        // 여기서 collection 초기화 하면서 위에서 정의한 클로저 실행.
        collection.collect { relativePath(it) }.sort().each { println it }
     
        srcDir = file('src2')
        println "Contents of $srcDir.name"
        // collection을 다시 초기화 하면서 위에서 정의한 클로저 재실행.
        collection.collect { relativePath(it) }.sort().each { println it }
    }
  • files()의 인자로 가능한 다른 타입들
    • FileCollection : 펼쳐진 상태로 추가된다.
    • Task : 태스크의 oputput 파일이 파일 컬렉션이 추가된다.
    • TaskOutputs : TaskOutputs의 출력 파일들이 추가된다.
  • 파일 컬렉션은 늦은 초기화로 수행된다. 즉, 미래에 만들어질 파일을 파일 컬렉션으로 만들어도 된다.

파일 Tree

  • FileTree Interface. 계층구조로 된 파일의 컬렉션. FileCollection을 구현하고 있다.
  • Project.fileTree() 메소드로 객체 생성.
  • Ant 스타일의 include/exclude가 가능하다.
  • FileTree 생성하는 법
    task list << {
        // 기준 디렉토리를 지정하여 FileTree 생성
        FileTree tree = fileTree(dir: 'src/main')
     
        // 패턴 추가/제외
        tree.include '**/*.java'
        tree.exclude '**/Abstract*'
     
        // 경로를 바로 줘서 생성
        tree = fileTree('src').include('**/*.java')
     
        // 클로저로 생성하기, 여러개씩 include, exclude
        tree = fileTree('src') {
            include '**/*.java'
            include '**/*.xml'
            exclude(['**/Abstract*', '**/*Test.java'])
        }
     
        tree.each { File file ->
            println file.absolutePath
        }
     
        // map으로 생성하기
        tree = fileTree(dir: 'src', include: '**/*.java')
        tree = fileTree(dir: 'src', includes: ['**/*.java', '**/*.xml'])
        tree = fileTree(dir: 'src', include: '**/*.java', exclude: '**/*test*/**')
    }
  • FileTree 용법 : FileCollection의 모든 용법을 포함한다.
    task list << {
        def tree = fileTree('src') {
            include '**/*.java'
            include '**/*.xml'
            exclude(['**/Abstract*', '**/*Test.java'])
        }
     
        // include에 매칭되는 것만 필터링
        FileTree filtered = tree.matching {
            include '**/*properties.xml'
        }
     
        filtered.each { File file ->
            println "Properties : ${file}"
        }
     
        FileTree sum = tree + fileTree(dir: 'src/test')
     
        tree.visit { element ->
            println "$element.relativePath => $element.file"
        }
    }
  • FileTree.matching(Closure)에서 PatternFilterable의 메소드들을 사용해 필터링 규칙을 정한다.
  • zipTree()tarTree()로 압축 파일에 대해 FileTree 객체 생성 가능.
    FileTree zip = zipTree('someFile.zip')
     
    FileTree tar = tarTree('someFile.tar')
     
    //tar tree는 압축형식을 파일 확장자로 스스로 판단하지만 (보통 *.tar.gz 형태)
    //압축 형태를 파일명으로 알 수 없을 때는 다음과 같이 명시한다.
    FileTree someTar = tarTree(resources.gzip('someTar.ext'))

입력 파일 묶음 지정

  • 다양한 곳에서 입력 파일 묶음을 지정해야 한다.(예: 자바 클래스 컴파일시 소스 파일 목록 등).
  • 이 입력 파일 묶은음 files() 로 생성가능한 모든 값을 지정할 수 있다. 즉, 다시말해 문자열, file, 컬렉션, FileCollection, FileTree 게다가 클로저를 이용할 수도 있다.
    // Use a File object to specify the source directory
    compile {
        source = file('src/main/java')
    }
     
    // Use a String path to specify the source directory
    compile {
        source = 'src/main/java'
    }
     
    // Use a collection to specify multiple source directories
    compile {
        source = ['src/main/java', '../shared/java']
    }
     
    // Use a FileCollection (or FileTree in this case) to specify the source files
    compile {
        source = fileTree(dir: 'src/main/java').matching { include 'org/gradle/api/**' }
    }
     
    // Using a closure to specify the source files.
    compile {
        source = {
            // Use the contents of each zip file in the src dir
            file('src').listFiles().findAll {it.name.endsWith('.zip')}.collect { zipTree(it) }
        }
    }
  • 대부분의 경우 입력 파일지정 프라퍼티는 동일한 이름의 메소드로도 호출 가능하다.
    compile {
        // Add some source directories use String paths
        source 'src/main/java', 'src/main/groovy'
     
        // Add a source directory using a File object
        source file('../shared/java')
     
        // Add some source directories using a closure
        source { file('src/test/').listFiles() }
    }

파일/디렉토리 관리

파일/디렉토리 관리는 Project 객체에 내장된 각종 메소드를 직접 호출하거나, Copy 등의 상위 태스크를 상속받아 태스크로 만드는 방식으로 처리할 수도 있다.

파일 복사

  • Copy 태스크로 파일을 복사한다.
  • 복사시 입력 소스와 출력 대상은 CopySpec 인터페이스의 메소드로 표현한다. Copy 태스크는 이 인터페이스를 구현하고 있다.
  • 기본 동작
    task copyTask(type: Copy) {
        from 'src/main/webapp'
        into 'build/explodedWar'
    }
  • from() 메소드는 files()에서 받을 수 있는 모든 인자를 받는다.
    • 인자가 디렉토리이면 그 디렉토리 이하 모든 파일(디렉토리 자체는 제외)을 복사
    • 인자파 파일이면 해당 파일만 복사
    • 인자가 존재하지 않는 파일이면 무시.
    • into() 메소드는 file()에서 받을 수 있는 모든 인자를 받는다.
  • from 예
    task anotherCopyTask(type: Copy) {
        // Copy everything under src/main/webapp
        from 'src/main/webapp'
        // Copy a single file
        from 'src/staging/index.html'
        // copyTask의 outputs
        from copyTask
        // copyTaskWithPatterns 태스크의 outputs 명시
        from copyTaskWithPatterns.outputs
        // Zip 파일 내용
        from zipTree('src/main/assets.zip')
        // Determine the destination directory later
        into { getDestDir() }
    }
  • 복사 대상을 상세히 명시
    task copyTaskWithPatterns(type: Copy) {
        from 'src/main/webapp'
        into 'build/explodedWar'
        include '**/*.html'
        include '**/*.jsp'
        exclude { details -> details.file.name.endsWith('.html') && details.file.text.contains('staging') }
    }
  • Project.copy() 메소드도 동일하게 사용할 수 있다.
    task copyMethod << {
        copy {
            from 'src/main/webapp'
            into 'build/explodedWar'
            include '**/*.html'
            include '**/*.jsp'
        }
    }

복사시 이름 변경

task rename(type: Copy) {
    from 'src/main/webapp'
    into 'build/explodedWar'
    // Use a closure to map the file name
    rename { String fileName ->
        fileName.replace('-staging-', '')
    }
    // Use a regular expression to map the file name
    rename '(.+)-staging-(.+)', '$1$2'
    rename(/(.+)-staging-(.+)/, '$1$2')
}

복사시 파일 내용 필터링(내용 변형)

import org.apache.tools.ant.filters.FixCrLfFilter
import org.apache.tools.ant.filters.ReplaceTokens
 
task filter(type: Copy) {
    from 'src/main/java'
    into 'build/filtered'
    // Substitute property references in files
    expand(copyright: '2009', version: '2.3.1')
    expand(project.properties)
 
    // Ant이용.
    filter(FixCrLfFilter)
    filter(ReplaceTokens, tokens: [copyright: '2009', version: '2.3.1'])
    // 모든 줄을 대괄호로 감싸기
    filter { String line ->
        "[$line]"
    }
}

CopySpec

  • CopySpec은 계층구조이다. 목표 경로, include/exclude 패턴, 복사 행위, 이름 매핑, 필터 등을 모두 상속한다.
  • nested copy specs
    apply plugin: 'java'
     
    repositories {
        mavenCentral()
    }
     
    dependencies {
        compile 'org.hibernate:hibernate-core:3.6.7.Final'
    }
     
    task nestedSpecs(type: Copy) {
        into 'build/explodedWar'
        exclude '**/*Test.java'
        from('src/main') {
            include '**/*.java'
        }
     
        // 아래 into는 위에서 선언한 build/explodedWar를 상속하여 그에 상대적인 경로이다.
        // 즉 buld/explodedWar/libs 를 뜻한다.
        into('libs') {
            // 모든 의존성 *.jar들을 libs 에 복사한다.
            from configurations.runtime
        }
    }

Sync

  • Copy를 상속한 태스크.
  • 두 폴더간의 싱크를 수행한다.
    apply plugin: 'java'
     
    repositories {
        mavenCentral()
    }
     
    dependencies {
        compile 'org.hibernate:hibernate-core:3.6.7.Final'
    }
     
    // 모든 의존성 *.jar들을 build/libs 에 복사한다.
    task libs(type: Sync) {
        from configurations.runtime
        into "$buildDir/libs"
    }

파일 압축

  • Jar, War, Zip, Tar 등을 지원한다.
  • 기본 용법
    apply plugin: 'java'
     
    task zip(type: Zip) {
        from 'src/dist'
        into('libs') { // 압축 파일 안의 libs/ 디렉토리로 파일 넣음
            from configurations.runtime
        }
    }
gradle/files.txt · 마지막으로 수정됨: 2014/06/27 11:48 저자 kwon37xi