'파일집합'에 해당되는 글 2건

  1. 2008.12.05 Buildr : 파일집합 복사하기
  2. 2008.12.01 Buildr : 파일 집합 선택

지난 글에서 FileList와 glob 패턴을 이용해서 파일 집합을 선택하는 방법을 알아보았습니다. 그럼 이렇게 선택된 파일들을 다른 디렉토리에 복사하는 방법을 살펴보겠습니다. 
음... web 디렉토리내의 *.html 및 *.gif 파일들을 target/htdocs 디렉토리로 한번 복사해볼까요?

FileList['web/**/*.{html,gif}'].exclude('web/WEB-INF').each do |file|
   cp file, 'target/htdocs'
end

FileList의 파일 목록을 each로 순회하면서 cp하고 있습니다. 오 쉽군요. 그러나........
cp 메소드는 파일을 타겟 디렉토리로 복사해주긴 하는데 경로를 유지하지는 않습니다. 말하자면 web/AA/a.html 파일과 web/AA/BB/b.html 파일은 각각 target/htdocs/a.html과  target/htdocs/b.html로 복사됩니다. 경로는 다르지만 파일명이 같다면 뒤에 복사된 파일이 먼저 파일을 덮어쓰게됩니다.

우리가 원하는 건 web/AA/a.html 파일은 target/htdocs/AA/a.html 로 복사되고 web/AA/BB/b.html은 target/htdocs/AA/BB/b.html로 복사되는 것입니다.

FileList['web/**/*.{html,gif}'].exclude('web/WEB-INF').each do |file|
  target = file.sub('web','target/htdocs')
  mkdir_p File.dirname(target)
  cp file, target
end

원래 파일 경로 'web/AA/BB/b.html'에서 'web'을 'target/htdocs'로 바꾼 뒤 타켓 디렉토리를 만들고(mkdir_p) 거기에 파일을 복사해주었습니다. 그런데 좀 지저분하군요. 깔끔한 방법이 없을까요?

제가 찾아낸 방법은 buildr에서 제공하는 filter() 메소드를 이용하는 것입니다.

filter('web').into('target/htdocs').include('**/*.html', '**/*.gif').exclude('WEB-INF/**/*').run

원래 buildr의 filter는 Maven의 리소스 필터처럼 리소스 파일의 내용을 필터링하기 위한 목적으로 만들어진 것입니다만, 이런식으로 filter()를 한 디렉토리 내의 파일집합을 다른 디렉토리로 복사하는데 이용할 수 있습니다.

참고로 filter는 내부적으로 File.fnmatch를 이용하는데 File.fnmatch가 받는 패턴은 { } 표현을 지원하지 않는다고 문서에 나옵니다. 예를 들어 filter()의 include, exclude 메소드에 '**/*.{html,gif}' 패턴을 넘겨주면 *.html이나 *.gif를 찾는 것이 아니라 "{html,gif}"라는 확장자를 가진 파일을 찾게 됩니다.
또한 FileList[].exclude('web/WEB-INF')와 filter().exclude('WEB-INF/**/*')도 약간 다른 것을 볼 수 있습니다. 패턴이 제대로 적용되는지 반드시 테스트해보시기 바랍니다.

신고

'Build&Deploy > Buildr' 카테고리의 다른 글

Buildr : 리소스 교체  (3) 2008.12.09
Buildr : 리소스 필터링  (0) 2008.12.09
Buildr : 파일집합 복사하기  (0) 2008.12.05
Buildr : 파일 집합 선택  (0) 2008.12.01
Buildr : 의존성(dependencies) 설정하기  (4) 2008.11.19
Buildr : 컴파일 옵션 설정하기  (2) 2008.11.18
Posted by 에코지오

댓글을 달아 주세요

루비 'fileutils.rb' 라이브러리에 보면 FileUtils 모듈이 있습니다. FileUtils에는 파일/디렉토리를 다루기 위한 기본적인 유틸리티 메소드가 정의되어 있는데, 메소드명은 유닉스에서 우리가 쓰던 명령과 유사합니다. cp(), mkdir(), rm(), mv() 처럼요 ....

rake는 기본적으로 이 FileUtils 모듈을 include하고 있기 때문에 rake에 기반을 두고 있는 buildr에서도 거리낌없이 FileUtils의 메소드를 사용할 수 있습니다.

mkdir 'build/myproject/bin'
cp 'src/abc.xml.dev' 'build/myproject/bin/abc.xml'

Ant에서는 <copy>, <mkdir>, <delete>, <move> 등의 코어 타스크를 이용하여 이런 작업을 처리했죠.( Maven은 maven-antrun-plugin 플러그인을 통해서 ant의 타스크를 간접 호출해서 작업을 합니다. 좀 귀찮죠)

 <copy file="myfile.txt" tofile="mycopy.txt"/>

작업할 파일이 하나가 아니면 어떡할까요? Ant에서는 파일의 집합을 FileSet으로 표현합니다.
예를들어 소스 디렉토리 내의 java 소스를 제외한 파일들을 빌드 디렉토리로 복사하는 작업은 아래처럼 정의할 수 있습니다. 여기서 **/*.java 와 같은 경로 표현은 Ant에서 정의한 패턴입니다. Ant style 경로패턴이라고도 하죠(?)

  <copy todir="../build/classes">
    <fileset dir="src_dir">
      <exclude name="**/*.java"/>
    </fileset>
  </copy>
            또는
  <copy todir="../build/classes">
    <fileset dir="src_dir" excludes="**/*.java"/>
  </copy>

rake/buildr에는 Ant의 FileSet에 대응하는 Rake::FileList 클래스가 있습니다. FileList는 주어진 glob 패턴과 매치되는 파일의 목록을 리턴합니다.

FileList['src_dir/**/*.java']
   => src_dir 디렉토리 내의 모든 .java 파일 목록 리턴

FileList['web/**/*'].exclude('**/*.jsp','web/WEB-INF') 
   => web 디렉토리 내의 .jsp 파일 및 WEB-INF 디렉토리를 제외한 모든 파일 목록 리턴

FileList와 비슷한 것으로 Dir.glob()이 있는데요, FileList는 CVS, .svn, .bak 등의 디렉토리/파일을 기본적으로 목록에서 제외하는 반면 Dir.glob()은 그런 것들도 포함해서 리턴합니다. 그러니까 빌드스크립트에서는 Dir.glob() 보다는 FileList를 쓰는게 좋습니다.

참고적으로 File.fnmatch(패턴,파일경로) 메소드가 있습니다. 이 메소드는 주어진 파일의 경로가 지정된 패턴에 부합하는지 판단합니다. FileList[]나 Dir.glob()과 마찬가지로 패턴은 glob 형식입니다.
주의하실 점은 FileList[패턴]의 패턴, FileList[].exclude(패턴)의 패턴, File.fnmatch(패턴)의 패턴이 조금씩 차이가 있는 것 같다는 겁니다. 반드시 적용전 테스트를 해보셔야 합니다. 그리고 File.fnmatch가 패턴은 { } 표현을 지원하지 않습니다. 즉 File.fnmatch()에서 'A.html' 파일은 '**/*.{html,gif}' 패턴과 매치하지 않습니다.

내용이 길어져서 파일집합에서 원하는 파일들만 복사하는 작업과 리소스 파일 치환에 대한 예제는 다음글로 넘깁니다.
신고
Posted by 에코지오

댓글을 달아 주세요



티스토리 툴바