ant:如何执行目录中的每个文件的命令?

我想从一个Ant构build文件执行一个命令,为一个目录中的每个文件。
我正在寻找一个独立于平台的解决scheme。

我该怎么做呢?

当然,我可以用某种脚本语言编写脚本,但是这会增加项目的依赖性。

简答

<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}目标“bar”。

使用<apply>任务 。

它为每个文件执行一次命令。 通过文件集或任何其他资源指定文件。 <apply>是内置的; 不需要额外的依赖; 没有需要定制的任务实现。

也可以只运行一次命令,将所有文件作为参数一次追加。 使用parallel属性来切换行为。

对不起,迟到了一年。

塔斯洛angular ( Tassilo Horn )提出了一个没有反作用的方法( 原来的目标是在这里 )

基本上,因为没有像扩展<exec>一样扩展<java> (yet?),所以他build议使用<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> 

ant是邪恶的; 编写一个自定义的ant任务。

ant-contrib是邪恶的,因为它试图将ant从一个声明风格转换为一个命令风格。 但是xml使得一个废话的编程语言。

相比之下,一个自定义的ant任务允许你写一个真正的语言(Java),一个真正的IDE,在那里你可以编写unit testing,以确保你有你想要的行为,然后在你的构build脚本你想要的行为。

如果你关心编写可维护的ant脚本,这个咆哮就很重要。 如果你不在乎可维护性,尽一切办法做。 🙂

JTF

我知道这个post是真的老了,但现在有一些时间和ant版本通过有一种方法来做到这一点与基本的antfunction,我想我应该分享它。

它通过调用嵌套任务的recursionmacros定义(甚至可能调用其他macros)完成。 唯一的约定是使用一个固定的variables名(元素在这里)。

 <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> 

做什么blak3rbuild议和像这样定义你的目标类path

 <taskdef resource="net/sf/antcontrib/antlib.xml"> <classpath> <fileset dir="lib"> <include name="**/*.jar"/> </fileset> </classpath> </taskdef> 

lib是你存储jar的地方