ฉันต้องการรันคำสั่งจาก Ant buildfile สำหรับแต่ละไฟล์ในไดเร็กทอรี
ฉันกำลังมองหาโซลูชันที่ไม่ขึ้นกับแพลตฟอร์ม
ฉันต้องทำอย่างไร
แน่นอนว่าฉันสามารถเขียนสคริปต์ในภาษาสคริปต์บางภาษาได้ แต่สิ่งนี้จะเพิ่มการอ้างอิงเพิ่มเติมให้กับโครงการ
ฉันต้องการรันคำสั่งจาก Ant buildfile สำหรับแต่ละไฟล์ในไดเร็กทอรี
ฉันกำลังมองหาโซลูชันที่ไม่ขึ้นกับแพลตฟอร์ม
ฉันต้องทำอย่างไร
แน่นอนว่าฉันสามารถเขียนสคริปต์ในภาษาสคริปต์บางภาษาได้ แต่สิ่งนี้จะเพิ่มการอ้างอิงเพิ่มเติมให้กับโครงการ
คำตอบ:
ใช้<foreach>
กับ<FileSet>
foreach ต้องมด 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>
การดำเนินการนี้จะเรียก "bar" เป้าหมายด้วย $ {theFile} ซึ่งส่งผลให้เกิดไฟล์ปัจจุบัน
ใช้<ใช้> งาน
เรียกใช้คำสั่งหนึ่งครั้งสำหรับแต่ละไฟล์ ระบุไฟล์โดยใช้ชุดไฟล์หรือทรัพยากรอื่น ๆ <apply> อยู่ในตัว; ไม่จำเป็นต้องพึ่งพาเพิ่มเติม ไม่จำเป็นต้องใช้งานแบบกำหนดเอง
นอกจากนี้ยังสามารถเรียกใช้คำสั่งเพียงครั้งเดียวโดยต่อท้ายไฟล์ทั้งหมดเป็นอาร์กิวเมนต์ในครั้งเดียว ใช้แอตทริบิวต์คู่ขนานเพื่อเปลี่ยนลักษณะการทำงาน
ขออภัยที่มาช้าไปปี
Tassilo Hornแนะนำแนวทางที่ไม่มีAnt- Contrib ( เป้าหมายเดิมอยู่ที่นี่ )
โดยพื้นฐานแล้วเนื่องจากไม่มีส่วนขยายของ<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 เป็นงานหลักของมด
<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 นั้นชั่วร้ายเพราะมันพยายามที่จะแปลงมดจากรูปแบบที่เปิดเผยเป็นรูปแบบที่จำเป็น แต่ xml สร้างภาษาโปรแกรมไร้สาระ
ในทางตรงกันข้ามงาน ant แบบกำหนดเองช่วยให้คุณสามารถเขียนในภาษาจริง (Java) ด้วย IDE จริงซึ่งคุณสามารถเขียนการทดสอบหน่วยเพื่อให้แน่ใจว่าคุณมีพฤติกรรมที่คุณต้องการจากนั้นทำการประกาศแบบสะอาดในสคริปต์บิลด์ของคุณเกี่ยวกับ พฤติกรรมที่คุณต้องการ
การพูดจาโผงผางนี้มีความสำคัญต่อเมื่อคุณสนใจเกี่ยวกับการเขียนสคริปต์มดที่ดูแลรักษาได้ หากคุณไม่สนใจเกี่ยวกับการบำรุงรักษาไม่ว่าจะทำอะไรก็ตาม :)
Jtf
ฉันรู้ว่าโพสต์นี้เก่าจริง แต่ตอนนี้เวลาและเวอร์ชันมดผ่านไปแล้วมีวิธีทำเช่นนี้ด้วยคุณสมบัติพื้นฐานของมดและฉันคิดว่าฉันควรแบ่งปัน
ทำได้โดยใช้ 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>
ทำตามที่ blak3r แนะนำและกำหนดคลาสพา ธ เป้าหมายของคุณเช่นนั้น
<taskdef resource="net/sf/antcontrib/antlib.xml">
<classpath>
<fileset dir="lib">
<include name="**/*.jar"/>
</fileset>
</classpath>
</taskdef>
โดยที่ lib คือที่ที่คุณเก็บขวดโหลของคุณ