Apache Ant – for loop example for reading a text file

The Ant-Contrib library also provides u a <for> task to do iteration. Here is an simple Ant example which read a text files and print it to the Ant build output.

1. This is the structure of our Ant project.

ant-for-example
  | - ant-lib
  |    | - ant-contrib-1.0b3.jar
  | - build.xml
  | - text.txt

 

2. text.txt

1. Hello World
2. Welcome to Eureka!
3. Goodbye

 

3. build.xml

<project name="ant-for-example" default="read" basedir=".">

  <!-- Load the ant contrib lib -->
  <taskdef resource="net/sf/antcontrib/antlib.xml">
    <classpath>
      <pathelement location="${basedir}/ant-lib/ant-contrib-1.0b3.jar"/>
    </classpath>
  </taskdef>

  <target name="read">
    <loadfile property="textFile" srcfile="${basedir}/text.txt"/>
    <for param="line" list="${textFile}" delimiter="${line.separator}">
      <sequential>
        <echo message="@{line}"/>
      </sequential>
    </for>
  </target>
</project>

 

4. Try it out.
ant-for-example
 

Done =)

Reference:

17 thoughts on “Apache Ant – for loop example for reading a text file”

  1. Hi YKYUEN,

    Thanks for the post.
    What i’m trying to achieve here is that i can print each separate line from the text file using this approach, but say in my case my file has 15 separate lines and each line is actually a single word, so i want that whenever for loop tries to retrieve the single word from the text file line by line it should store that or pass that as value to another variable that could be part of the another target called from within that target.
    Please refer the below stackoverflow link to answer my question:-
    http://stackoverflow.com/questions/36164609/read-one-word-line-from-a-text-file-and-store-that-in-a-variable-in-ant-build-fi

    Like

      1. Hi Ykyuen,

        Thanks for the prompt response.
        I now have a slightly different requirement.
        It says i have 4 different text files each with say 3 lines (each line is a one word string for all files).
        Now i need a foreach loop in ant that reads all 4 files at same time for the first line in each file and stores the values accordingly as 4 different properties. This way for every single iteration of loop i can refer to a target where i can pass these properties for target execution.
        The loop will hence run 3 times and execute that target 3 times one for each iteration.
        Any suggestions/help here would be highly appreciated.

        Thanks,
        Ashley

        Like

  2. Hi Ykyuen,

    Once again thanks for the prompt response.
    Let say i have 3 text files each with 3 lines and each line is a single word(number of lines in the files could be anything but same for all files, so all files will have same number of lines).
    Let first file has below 3 lines:-
    stub1
    stub2
    stub3

    Second file has:-
    ver1
    ver2
    ver3
    Third one has:-
    comp1
    comp2
    comp3

    Now i would like an ant loop or something that can pick first line from each file and pas them as parameter to my destination target as part of first iteration. Then second line from each for second iteration and so on.
    My Sample code is:-

    Looking forward to your response on this.

    Thanks,
    Ashley

    Like

    1. 
      <target name="read">
      <loadfile property="file" srcfile="./dist/DB_Critical_Stub_Data.txt"/>
      <loadfile property="fileversion" srcfile="./dist/version.txt"/>
      <loadfile property="filecomponent" srcfile="./dist/component.txt"/>
      <foreach list="${file},${fileversion},${filecomponent}" param="line,line1,line2" delimiter="${line.separator}" target="start-stub"/>
      </target>
      <target name="start-stub">
      <property name="stub-name" value="${line}"/>
       <property name="stub-version" value="${line1}"/>
       <property name="stub-component" value="${line2}"/>
       <startStub name="${stub-name}" version="${stub-version}" component="${stub-component"}/>
       </target>
      
      

      Like

      1. <project name="ant-read-n-files" default="run" basedir=".">
         
          <!-- Load the ant contrib lib -->
          <taskdef resource="net/sf/antcontrib/antlib.xml">
            <classpath>
              <pathelement location="${basedir}/lib/ant-contrib.jar"/>
            </classpath>
          </taskdef>
         
          <target name="read">
            <!-- file a -->
            <loadfile property="textFileA" srcfile="${basedir}/files/aaa.txt">
              <filterchain>
                <headfilter lines="1" skip="${linenum}"/>
              </filterchain>
            </loadfile>
            <for param="line" list="${textFileA}" delimiter="${line.separator}">
              <sequential>
                <property name="textFileAValue" value="@{line}"/>
              </sequential>
            </for>
            <!-- file b -->
            <loadfile property="textFileB" srcfile="${basedir}/files/bbb.txt">
              <filterchain>
                <headfilter lines="1" skip="${linenum}"/>
              </filterchain>
            </loadfile>
            <for param="line" list="${textFileB}" delimiter="${line.separator}">
              <sequential>
                <property name="textFileBValue" value="@{line}"/>
              </sequential>
            </for>
            <!-- file c -->
            <loadfile property="textFileC" srcfile="${basedir}/files/ccc.txt">
              <filterchain>
                <headfilter lines="1" skip="${linenum}"/>
              </filterchain>
            </loadfile>
            <for param="line" list="${textFileC}" delimiter="${line.separator}">
              <sequential>
                <property name="textFileCValue" value="@{line}"/>
              </sequential>
            </for>
        
            <!-- Print them all -->
            <echo message="${textFileAValue}"/>
            <echo message="${textFileBValue}"/>
            <echo message="${textFileCValue}"/>
          </target>
        
          <target name="run">
            <foreach param="linenum" list="0,1,2" target="read"/>
          </target>
        </project>
        

        Like

  3. Many thanks Ykyuen for such great solution. It works perfectly.
    Only one thing i would like to implement here is that for each file the number of lines will be same but not fixed (necessarily 3 here) so how can we modify here so that it only picks the number of lines as they are in the files sometimes could be 3 sometimes 2 sometimes 4,etc

    Thanks,
    Ashley

    Like

      1. Could you please help me implement resource count for the above code where list=”0,1,2″
        I fail to get that work

        Thanks,
        Ashley

        Like

      2. I am already very thankful for the great solutions you have provided so far.
        but this one where using resource count i should be able to limit the loop based on the exact number of lines in the text file, my way of implementing/trying it out isn’t yielding true results.
        I would very much appreciate if i can somehow manage to get this last step implemented.
        So really looking forward to your response on this and very much appreciate that as always.

        Thanks,
        Ashley

        Like

      3. <project name="ant-read-n-files" default="run" basedir=".">
         
          <!-- Load the ant contrib lib -->
          <taskdef resource="net/sf/antcontrib/antlib.xml">
            <classpath>
              <pathelement location="${basedir}/lib/ant-contrib.jar"/>
            </classpath>
          </taskdef>
         
          <target name="read">
            <!-- file a -->
            <loadfile property="textFileA" srcfile="${basedir}/files/aaa.txt">
              <filterchain>
                <headfilter lines="1" skip="${linenum}"/>
              </filterchain>
            </loadfile>
            <for param="line" list="${textFileA}" delimiter="${line.separator}">
              <sequential>
                <property name="textFileAValue" value="@{line}"/>
              </sequential>
            </for>
            <!-- file b -->
            <loadfile property="textFileB" srcfile="${basedir}/files/bbb.txt">
              <filterchain>
                <headfilter lines="1" skip="${linenum}"/>
              </filterchain>
            </loadfile>
            <for param="line" list="${textFileB}" delimiter="${line.separator}">
              <sequential>
                <property name="textFileBValue" value="@{line}"/>
              </sequential>
            </for>
            <!-- file c -->
            <loadfile property="textFileC" srcfile="${basedir}/files/ccc.txt">
              <filterchain>
                <headfilter lines="1" skip="${linenum}"/>
              </filterchain>
            </loadfile>
            <for param="line" list="${textFileC}" delimiter="${line.separator}">
              <sequential>
                <property name="textFileCValue" value="@{line}"/>
              </sequential>
            </for>
        
            <!-- Print them all -->
            <echo message="${textFileAValue}"/>
            <echo message="${textFileBValue}"/>
            <echo message="${textFileCValue}"/>
          </target>
        
          <target name="run">
            <!-- Get number of lines of one of the files -->
            <loadfile property="textFile" srcfile="${basedir}/files/aaa.txt"/>
            <resourcecount property="line.count" count="0" when="eq">
              <tokens>
                <concat>
                  <filterchain>
                    <tokenfilter>
                      <stringtokenizer delims="${line.separator}" />
                    </tokenfilter>
                  </filterchain>
                  <propertyresource name="textFile" />
                </concat>
              </tokens>
            </resourcecount>
            <echo message="Number of lines: ${line.count}" />
        
            <script language="javascript">
              var list="", n=parseInt(project.getProperty("line.count"), 0);
              for (var i = 0; i &lt; n; i++) list += i + ",";  
              project.setProperty("list", list);
            </script>
            <foreach param="linenum" list="${list}" target="read"/>
        
          </target>
        </project>
        

        Like

  4. Perfect that works like a charm:)
    Many thanks for such great solutions so far.
    Really appreciate it:)

    Like

  5. Hi Ykyuen,

    I have a different situation here, I want FOR loop in ANT which would replace just a number after the “variablename”.

    What I am trying here is, I am installing 3 WildFly instances using a build.xml file and a properties file which has variables already defined like-

    My Env.properties file have-

    WildFly_Service_Name1=process_node1
    WildFly_Service_Name2=process_node2
    WildFly_Service_Name3=UI_node1

    Currently I am executing a powershell module from buld.xml and providing it the variables with their actual names retrieved from properties file, like-

    What I want is, define only one such “exec” statement which would iterate number of times for example 3 times but each time it would increase the number which is in the variable for Ex. ${wildfly_service_name1}, ${wildfly_service_name2}, ${wildfly_service_name3}.
    Each time it would take the value of each variable which are already mentioned in the properties file.

    I tried this from here-
    https://stackoverflow.com/questions/20265016/iterate-over-for-loop-with-fixed-amount-of-iterations

    But it would nor replacing the number, it just iterates the target number of times I want.

    Can I get help from you please?

    Thanks in Advance

    Like

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.