ディレクトリ内の各ファイルに対して、Antビルドファイルからコマンドを実行したい。
プラットフォームに依存しないソリューションを探しています。
どうすればよいですか?
もちろん、スクリプト言語でスクリプトを書くこともできますが、これによりプロジェクトにさらに依存関係が追加されます。
ディレクトリ内の各ファイルに対して、Antビルドファイルからコマンドを実行したい。
プラットフォームに依存しないソリューションを探しています。
どうすればよいですか?
もちろん、スクリプト言語でスクリプトを書くこともできますが、これによりプロジェクトにさらに依存関係が追加されます。
回答:
<foreach>
入れ子で使用<FileSet>
Foreachにはant-contribが必要です。
最近のant-contribの例を更新:
<target name="foo">
<foreach target="bar" param="theFile">
<fileset dir="${server.src}" casesensitive="yes">
<include name="**/*.java"/>
<exclude name="**/*Test*"/>
</fileset>
</foreach>
</target>
<target name="bar">
<echo message="${theFile}"/>
</target>
これにより、ターゲットの「バー」が$ {theFile}で呼び出され、現在のファイルが生成されます。
<apply>タスクを使用します。
ファイルごとにコマンドを1回実行します。ファイルセットまたはその他のリソースを使用してファイルを指定します。<apply>は組み込みです。追加の依存関係は必要ありません。カスタムタスクの実装は必要ありません。
コマンドを一度だけ実行して、すべてのファイルを引数として一度に追加することもできます。動作を切り替えるには、parallel属性を使用します。
一年遅れてすみません。
ant-contribを使用しないアプローチはTassilo Hornによって提案されています(元のターゲットはここにあります)
<app >が<exec>を拡張するのと同じ方法で(まだ?)<java>の拡張はないため、基本的に<apply>を使用することをお勧めします(もちろん、コマンドラインでJavaプログラムを実行することもできます)。
ここにいくつかの例があります:
<apply executable="java">
<arg value="-cp"/>
<arg pathref="classpath"/>
<arg value="-f"/>
<srcfile/>
<arg line="-o ${output.dir}"/>
<fileset dir="${input.dir}" includes="*.txt"/>
</apply>
これは、javascriptとant scriptdefタスクを使用してこれを行う方法です。scriptdefはコアantタスクであるため、このコードが機能するためにant-contribは必要ありません。
<scriptdef name="bzip2-files" language="javascript">
<element name="fileset" type="fileset"/>
<![CDATA[
importClass(java.io.File);
filesets = elements.get("fileset");
for (i = 0; i < filesets.size(); ++i) {
fileset = filesets.get(i);
scanner = fileset.getDirectoryScanner(project);
scanner.scan();
files = scanner.getIncludedFiles();
for( j=0; j < files.length; j++) {
var basedir = fileset.getDir(project);
var filename = files[j];
var src = new File(basedir, filename);
var dest= new File(basedir, filename + ".bz2");
bzip2 = self.project.createTask("bzip2");
bzip2.setSrc( src);
bzip2.setDestfile(dest );
bzip2.execute();
}
}
]]>
</scriptdef>
<bzip2-files>
<fileset id="test" dir="upstream/classpath/jars/development">
<include name="**/*.jar" />
</fileset>
</bzip2-files>
project
上記の例では変数が参照されていますが、事前の定義はありません。それを表現したり、明確にしたりするとよいでしょう。編集:n / m、project
現在のプロジェクトにアクセスするための事前定義の変数であることがわかりました。私はそれを疑っていたが、確信が持てなかった。
ant-contribは悪です。カスタムantタスクを記述します。
ant-contribは、antを宣言型スタイルから命令型スタイルに変換しようとするため、悪です。しかし、xmlは粗末なプログラミング言語を作ります。
対照的に、カスタムantタスクを使用すると、実際のIDEを使用して実際の言語(Java)で記述できるため、ユニットテストを記述して必要な動作を確認し、ビルドスクリプトで明確な宣言を行うことができます。あなたが望む行動。
これは、保守可能なAntスクリプトを作成することに関心がある場合にのみ重要です。メンテナンス性を気にしないのであれば、何でもうまくいきます。:)
JTF
私はこの投稿が本当に古いことを知っていますが、いくつかの時間とantバージョンが渡されたので、基本的なant機能でこれを行う方法があり、共有する必要があると思いました。
ネストされたタスクを呼び出す再帰的なmacrodefを介して行われます(他のマクロも呼び出される可能性があります)。唯一の規則は、固定変数名(ここでは要素)を使用することです。
<project name="iteration-test" default="execute" xmlns="antlib:org.apache.tools.ant" xmlns:if="ant:if" xmlns:unless="ant:unless">
<macrodef name="iterate">
<attribute name="list" />
<element name="call" implicit="yes" />
<sequential>
<local name="element" />
<local name="tail" />
<local name="hasMoreElements" />
<!-- unless to not get a error on empty lists -->
<loadresource property="element" unless:blank="@{list}" >
<concat>@{list}</concat>
<filterchain>
<replaceregex pattern="([^;]*).*" replace="\1" />
</filterchain>
</loadresource>
<!-- call the tasks that handle the element -->
<call />
<!-- recursion -->
<condition property="hasMoreElements">
<contains string="@{list}" substring=";" />
</condition>
<loadresource property="tail" if:true="${hasMoreElements}">
<concat>@{list}</concat>
<filterchain>
<replaceregex pattern="[^;]*;(.*)" replace="\1" />
</filterchain>
</loadresource>
<iterate list="${tail}" if:true="${hasMoreElements}">
<call />
</iterate>
</sequential>
</macrodef>
<target name="execute">
<fileset id="artifacts.fs" dir="build/lib">
<include name="*.jar" />
<include name="*.war" />
</fileset>
<pathconvert refid="artifacts.fs" property="artifacts.str" />
<echo message="$${artifacts.str}: ${artifacts.str}" />
<!-- unless is required for empty lists to not call the enclosed tasks -->
<iterate list="${artifacts.str}" unless:blank="${artifacts.str}">
<echo message="I see:" />
<echo message="${element}" />
</iterate>
<!-- local variable is now empty -->
<echo message="${element}" />
</target>
</project>
必要な主な機能:
私はなんとかデリミタを可変にできませんでしたが、これは大きな欠点ではないかもしれません。
ant-contribタスク「for」を使用して、区切り文字で区切られたファイルのリストを反復できます。デフォルトの区切り文字は「、」です。
以下は、これを示すサンプルファイルです。
<project name="modify-files" default="main" basedir=".">
<taskdef resource="net/sf/antcontrib/antlib.xml"/>
<target name="main">
<for list="FileA,FileB,FileC,FileD,FileE" param="file">
<sequential>
<echo>Updating file: @{file}</echo>
<!-- Do something with file here -->
</sequential>
</for>
</target>
</project>