चींटी: निर्देशिका में प्रत्येक फ़ाइल के लिए एक कमांड निष्पादित कैसे करें?


97

मैं एक निर्देशिका में प्रत्येक फ़ाइल के लिए एक चींटी buildfile से एक कमांड निष्पादित करना चाहते हैं।
मैं एक प्लेटफार्म-स्वतंत्र समाधान की तलाश में हूं।

मैं यह कैसे करु?

ज़रूर, मैं कुछ स्क्रिप्टिंग भाषा में एक स्क्रिप्ट लिख सकता था, लेकिन इससे परियोजना पर और निर्भरता बढ़ जाएगी।

जवाबों:


61

संक्षिप्त जवाब

<foreach>नेस्टेड के साथ प्रयोग करें<FileSet>

Foreach के लिए एंटी- कंट्रीब की आवश्यकता होती है ।

हालिया एंटी-कंट्रीब के लिए अपडेट किया गया उदाहरण:

<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} के साथ लक्ष्य "बार" का विरोध करेगा।


तो, मुझे कुछ शामिल करना होगा? या क्या मुझे कुछ बाहरी चींटी लिब की जरूरत है? मुझे "समस्या: कार्य बनाने में विफल रहा है या फॉर्चून टाइप कर रहा हूँ " । अगर मैं सही तरीके से समझूं , तो इसका मतलब है, फॉरच्यू अनजान कीवर्ड है।
ivan_ivanovich_ivanoff

4
ओह्ह लंगड़ा ... यह एक एंट-कंट्रिब टास्क है। तो, आपको कुछ स्थापित करना होगा। यहां देखें: ant-contrib.sourceforge.net
blak3r

3
एंटी-कंट्रीब में शामिल होने से पहले यह उदाहरण एक फॉर्च से है। Ant.1045680.n5.nabble.com/Using-foreach-td1354624.html पर एक अच्छा उदाहरण है मैं काम करने के लिए उदाहरण को अपडेट करने जा रहा हूं।
शॉन

2
नेस्टेड फ़ाइलसेट तत्व को हटा दिया गया है, इसके बजाय नेस्टेड पथ का उपयोग करें
यार

@dude का उपयोग करें <foreach> <path> <fileset> <इसमें name = "*। jar" /> </ fileset> </ path> </ foreach>
शरत

88

<Apply> कार्य का उपयोग करें ।

यह प्रत्येक फ़ाइल के लिए एक बार एक कमांड निष्पादित करता है। फ़ाइलों को फाइलसेट या किसी अन्य संसाधन के माध्यम से निर्दिष्ट करें। <लागू करें> अंतर्निहित है; कोई अतिरिक्त निर्भरता की जरूरत; कोई कस्टम कार्य कार्यान्वयन की आवश्यकता नहीं है।

सभी फाइलों को एक बार में तर्क के रूप में जोड़कर केवल एक बार कमांड चलाना संभव है। व्यवहार को स्विच करने के लिए समानांतर विशेषता का उपयोग करें।

एक साल देर से आने के लिए क्षमा करें।


4
वैसे मुझे यह 2011 में उपयोगी लगा, इसलिए इसके लिए धन्यवाद!
माइकल डेला बिट्टा

7
<लागू करें> के साथ समस्या यह है कि यह केवल बाहरी सिस्टम कमांड निष्पादित करता है। यह सीधे कोई भी सामान नहीं करेगा। स्पष्ट नहीं है कि मूल प्रश्न क्या था या नहीं। मूल रूप से आपको दो अलग-अलग स्थितियों के लिए <apply> या <foreach> का उपयोग करना होगा ... जो पूरी तरह से गूंगा है।
आर्ची

27

टैसिलो हॉर्न द्वारा मूल -विरोधी के बिना एक दृष्टिकोण का सुझाव दिया गया है ( मूल लक्ष्य यहां है )

मूल रूप से, जैसा कि <java> (अभी तक?) का कोई विस्तार नहीं है, उसी तरह से <लागू करें> <निष्पादन> का विस्तार करता है , वह <apply> का उपयोग करने का सुझाव देता है (जो निश्चित रूप से एक कमांड लाइन में जावा प्रोग्राम भी चला सकता है)

यहाँ कुछ उदाहरण हैं:

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

2
यह बहुत ही स्वतंत्र मंच नहीं है, हालांकि मूल प्रश्न में यह स्पष्ट रूप से आवश्यक था ...
चकु

18

यहाँ जावास्क्रिप्ट और चींटी स्क्रिप्टेड टास्क का उपयोग करके ऐसा करने का तरीका है, आपको इस कोड के लिए एंटी-कंट्रीब की जरूरत नहीं है क्योंकि स्क्रिप्टडेफ एक मुख्य चींटी का काम है।

<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वर्तमान परियोजना तक पहुँचने के लिए पूर्वनिर्धारित संस्करण है। मुझे उस पर शक था, लेकिन यकीन नहीं था।
जॉन एल।

2
JDK8 या बाद में इसे आज़माने वालों के लिए, ध्यान रखें कि "importClass" काम करता है यदि JRE द्वारा लोड की गई ScriptEngine राइनो है (जो कि ज्यादातर JDK 6 और 7 के लिए सही थी), जबकि नैशॉर्न में (8 सेवर्ड से) आप उपयोग कर सकते हैं। पिछड़े-संगत "फ़ाइल = java.io.File" या नए लेकिन पिछड़े-संगत Java.type नहीं। जब मैं आज अनुभव करने के लिए मिला, तो पटकथा को चलाने में समस्या होने पर चींटी चुपचाप विफल हो जाती है।
मैटेको स्टैकोलिनी

16

एंटी-कंट्राब बुराई है; एक कस्टम चींटी कार्य लिखें।

ant-contrib बुराई है क्योंकि यह चींटी को एक घोषणात्मक शैली से अनिवार्य शैली में बदलने की कोशिश करता है। लेकिन xml एक क्रैप प्रोग्रामिंग भाषा बनाता है।

इसके विपरीत एक कस्टम चींटी कार्य आपको एक वास्तविक आईडीई के साथ एक वास्तविक भाषा (जावा) में लिखने की अनुमति देता है, जहां आप यह सुनिश्चित करने के लिए इकाई परीक्षण लिख सकते हैं कि आपके पास जो व्यवहार है वह आप चाहते हैं, और फिर अपनी बिल्ड स्क्रिप्ट में एक साफ घोषणा करें। वह व्यवहार जो आप चाहते हैं।

यह शेख़ी तभी मायने रखती है जब आप बनाए रखने योग्य चींटी स्क्रिप्ट लिखने की परवाह करते हैं। यदि आप हर तरह से रखरखाव की परवाह नहीं करते हैं, तो जो भी काम करता है। :)

जेटीएफ


2
आप सही हैं, मुझे सिर्फ जावा में एक कस्टम चींटी कार्य लिखना चाहिए;)
ivan_ivanovich_ivanoff

4
एंटी-कंट्रीब वास्तव में बुराई है। अभी मैं एक बड़ी चींटी निर्माण परियोजना के बीच में हूं जो अगर / फिर / और एंटीकॉल का गहन उपयोग करती है और यह वास्तव में भयानक है। पूरी चीज एक रूपांतरित बैच / शेल स्क्रिप्ट और सभी निर्भरता वाले सामान की तरह दिखती है जो चींटी करता है पूरी तरह से एंटी-कंटिब के भारी उपयोग से बंद हो जाता है। यदि आप अपना सेटअप साफ़ रखना चाहते हैं, तो अपना कार्य स्वयं बनाएँ। : - /
cringe

2
@ क्रिंग, मैं असहमत हूं। किसी भी चीज की तरह, आपको यह जानना होगा कि एंट-कॉन्ट्रिब का उपयोग करना आपके सर्वोत्तम हित में है। अगर और var जैसी चीजों से दूर रहें और पहिया को फिर से लगाने से बचने के लिए एंटी-कंट्राब का उपयोग करें।
नील

1
और एक स्क्रिप्टिंग भाषा होनी चाहिए, ताकि शुरू होने के लिए इतना जरूरी और घोषित न हो। तो यह है और जो बुराई IMO है
mvmn

हो सकता है कि एंटी-कंट्रीब एक प्राथमिक बुराई है, लेकिन ब्लैक 3 आर का उपयोग उचित और एंटी-ईश लगता है, इसलिए बोलने के लिए।
एसएसएम

7

मुझे पता है कि यह पोस्ट वास्तव में पुरानी है, लेकिन अब जब कुछ समय और चींटी संस्करण पारित हो गए हैं, तो मूल चींटी सुविधाओं के साथ ऐसा करने का एक तरीका है और मुझे लगा कि मुझे इसे साझा करना चाहिए।

यह एक पुनरावर्ती 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>

प्रमुख विशेषताएं जहां आवश्यक हैं:

मैंने परिसीमन परिवर्तनशील बनाने का प्रबंधन नहीं किया, लेकिन यह एक बड़ा नकारात्मक पहलू नहीं हो सकता।


दुर्भाग्य से यह स्मृति से बाहर चलाता है और जल्दी से ऊपर उड़ जाता है।
डेविड सेंट डेनिस

हाँ, यह आपके स्टैक को उड़ा सकता है, आपके द्वारा प्रोसेस की जाने वाली फ़ाइलों की संख्या पर निर्भर करता है। मैंने इसे लगभग 66 फाइलों (बिना मेमोरी विकल्पों में वृद्धि के) के साथ सफल बनाया। हालांकि यह केवल एक विकल्प के कारण होता है यदि आपके पास एंटी-कंट्रीब वाईच तक पहुंच नहीं है, जो अधिक कार्यक्षमता प्रदान करता है (जैसे समानांतर चल रहा है)।
दाग

यह बहुत मददगार था।
डायमंडड्रैक

0

आप "किसी भी परिधि द्वारा अलग की गई फ़ाइलों की सूची पर पुनरावृत्ति करने के लिए", "डिफ़ॉल्ट रूप से", "के लिए" के लिए एंटी-कंट्रीब कार्य का उपयोग कर सकते हैं।

निम्नलिखित नमूना फ़ाइल है जो यह दिखाती है:

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

0

ऐसा करें कि blak3r ने सुझाव दिया और अपने लक्ष्य वर्गपथ को इस तरह परिभाषित करें

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

जहाँ आप अपने जार की दुकान है, वहां देयता है

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.