Property vs. Var
상수인 Property은 하위 Target 에게 보이지 않지만, 변수인 Var 는 보인다.
특정 확장자를 가진 파일만 삭제하기(recursive)
<delete>
<fileset dir="${dir}/.." includes="**/*.js"/>
</delete>
특정 폴더 이하 모든 하위 폴더를 삭제하기(빈 폴더 포함)
<delete includeemptydirs="yes">
<fileset dir="${dir}" includes="**/*"/>
</delete>
정규식을 이용해서 파일 이름 바꾸기
apply task 보다는 move task + regexpmapper 를 이용하면 간단하다. move 는 대상 폴더가 없으면 무조건 만들기 때문에 편하다!
<!--
<apply executable="mv">
<fileset dir="${dir}" includes="*.png"/>
-v"/>
<srcfile/>
<targetfile/>
<regexpmapper from="^_\d\d\d\d_(.*)\.png$" to="${dir}/\1.png"/>
</apply>
-->
<move todir="${dir}">
<fileset dir="${dir}" includes="*.png"/>
<regexpmapper from="_\d\d\d\d_(.*)\.png" to="\1.png"/>
</move>
경로에서 부모 폴더(dirname)와 파일명(basename)으로 분리하기
basename 의 suffix 를 지정하면 확장자 없는 순수 파일명만 저장할 수 있다.
<dirname property="parentdir" file="${file}"/>
<basename property="basename" file="${file}" suffix=".png"/>
파일명에 정규식을 적용해서 속성에 저장하기
propertyregex 를 이용하면 된다. 이때 디폴트값을 정해줄 수도 있다.
<propertyregex property="output"
input="${file}"
regexp="(.+?)_(.+)"
select="\2"
defaultValue="${default}"/>
하위 폴더 각각에 대해서 특정 타겟을 실행하기
foreach task 를 이용하면 된다. 이때 dirset 은 항상 부모 폴더 자신(./)을 포함하는데, excludes=./ 등으로 자신을 제거할 수 없으므로, 아래처럼 includes=/* 으로 제외할 수 있다.
<foreach param="dir" target="xxx">
<path>
<dirset dir="${parentdir}" includes="*/**"/>
</path>
</foreach>
Exec vs. Apply
exec 는 커맨드라인 명령을 1회 실행하지만, apply 는 특정 집합에 대해서 for 루프처럼 실행이 가능하다.
이때 arg value 는 -v 나 -f 같은 단일 파라미터이고, arg line 은 --output xxx 처럼 공백이 들어가는 긴 파라미터에 사용한다.
또한 regexpmapper 를 이용해서 targetfile 에 대해 정규식을 적용할 수도 있다.
<exec executable="${file.python}">
<arg value="trim.py"/>
<arg value="--verbose"/>
json ${trim.dir}/anchor.json"/>
<arg value="${trim.dir}"/>
</exec>
<apply executable="${file.python}">
<fileset dir="${flip.dir}" includes="*.png" excludes="*.r.png"/>
<arg value="flip.py"/>
<arg value="--verbose"/>
<arg value="-o"/>
<targetfile/>
<srcfile/>
<regexpmapper from="(.*)\.png$" to="${flip.dir}/${flip.default}.png"/>
</apply>
파일 출력
echo task를 이용하면 화면 출력 뿐만 아니라, 파일에 임의의 문자열을 append를 할 수 있다. 이걸 이용하면 concat task 를 쓰지 않고도 header 나 footer 를 간단하게 넣을 수 있다.
<echo file="${script}" append="yes">
sprites = sprites || {};
sprites.data = sprites.data || {};
</echo>
파일 이어붙일 때 필터링하기
filterchain 을 이용해서 특정 문자열을 포함한 라인을 제거하거나, tokenfilter + replaceregex 를 이용해서 문자열을 바꿀 수도 있다.
<concat destfile="${script}" append="yes">
<path>
<filelist dir="${dir}" files="${json}" />
</path>
<filterchain>
<linecontains negate="true">
<contains value="trimmed"/>
</linecontains>
<tokenfilter>
<!--
<replaceregex pattern="\{"frames"\:" replace='sprites["${spritename}"] =' flags="g"/>
-->
<!-- remove .<span class="hiddenSpellError" pre="remove ">png</span> -->
<replaceregex pattern="\.png" replace='' flags="g"/>
</tokenfilter>
</filterchain>
</concat>
파일을 복사하면서 이름 바꾸기
copy task 와 globmapper 를 쓰면 파일을 복사하면서 단순하게 이름을 바꿀 수 있다.
<copy todir="${destdir}">
<fileset dir="${srcdir}" includes="*.png"/>
</copy>
<copy todir="${destdir}">
<filelist dir="${srcdir}" files="${src}.js"/>
<mapper type="glob" from="*.js" to="sprite.*.js"/>
</copy>
명령 실행시 입력 리다이렉트 적용하기
잘 알려지진 않았지만, 구글 앱엔진의 패스워드를 파일에 저장한 후, appcfg.py --passin < file 을 이용하면 자동화가 가능하다. ant 에서는 exec 의 inputstring 으로 대체할 수 있다.
<exec executable="appcfg.py" inputstring="${bulkload.pass}">
<arg value="${bulkload.cmd}"/>
<arg line="--application=${bulkload.appid}"/>
<arg value="--config_file=${bulkload.config}"/>
<arg value="--email=${bulkload.email}"/>
<arg value="--url=${bulkload.url}"/>
<arg value="--kind=${bulkload.kind}"/>
<arg value="--filename=${bulkload.csv}"/>
<arg value="--no_cookies"/>
passin"/>
<arg value="."/>
</exec>