Я хочу виконати команду з файлу збірки Ant для кожного файлу в каталозі.
Я шукаю рішення, незалежне від платформи.
Як це зробити?
Звичайно, я міг би написати сценарій якоюсь мовою сценаріїв, але це додало б подальших залежностей до проекту.
Я хочу виконати команду з файлу збірки Ant для кожного файлу в каталозі.
Я шукаю рішення, незалежне від платформи.
Як це зробити?
Звичайно, я міг би написати сценарій якоюсь мовою сценаріїв, але це додало б подальших залежностей до проекту.
Відповіді:
Використовуйте <foreach>
з вкладеними<FileSet>
Foreach вимагає мурашиного вкладу .
Оновлений приклад нещодавнього 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> вбудований; не потрібна додаткова залежність; не потрібне виконання спеціального завдання.
Також команду можна запустити лише один раз, додавши всі файли як аргументи за один раз. Використовуйте паралельний атрибут, щоб змінити поведінку.
Вибачте, що запізнився на рік.
Тассіло Горн пропонує підхід без мурашника ( оригінальна мета тут )
По суті, оскільки розширення <java> (ще?) Не існує так само, як <apply> розширює <exec> , він пропонує використовувати <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, вам не потрібно ant-contrib, щоб цей код працював, оскільки scriptdef є основним завданням ant.
<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
посилається у наведеному вище прикладі, але без попереднього визначення. Було б добре, щоб це було представлено або роз’яснено. EDIT: n / m, виявлено, що project
це заздалегідь визначена змінна для доступу до поточного проекту. Я підозрював це, але не був впевнений.
мурашиний внесок - це зло; написати власне мурашине завдання.
ant-contrib - це зло, оскільки він намагається перетворити мураха з декларативного стилю в імперативний. Але xml робить моту програмування безглуздо.
На відміну від цього, спеціальне мурашине завдання дозволяє писати справжньою мовою (Java) із справжньою IDE, де ви можете писати модульні тести, щоб переконатися, що маєте потрібну поведінку, а потім зробити чисту заяву у сценарії збірки про поведінку, яку ви хочете.
Ця зухвалість має значення лише в тому випадку, якщо ви переймаєтеся написанням скриптів, що підтримуються. Якщо ви не переймаєтесь ремонтом, будь-якими способами зробіть все, що спрацює. :)
Jtf
Я знаю, що ця публікація справді стара, але тепер, коли пройшло деякий час та версії мурашок, є спосіб зробити це з основними характеристиками мурашок, і я подумав, що я повинен поділитися нею.
Це робиться через рекурсивний макродеф, який викликає вкладені завдання (можуть бути викликані навіть інші макроси). Єдиною умовою є використання фіксованого імені змінної (тут елемент).
<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>