質問

I need to iterate over all files in a directory. But I need just the name of each file, not absolute paths. Here's my attempt using ant-contrib:

<target name="store">
  <for param="file">
    <path>
      <fileset dir="." includes="*.xqm"/>
    </path>
    <sequential>
      <basename file="@{file}" property="name" />
      <echo message="@{file}, ${name}"/>
    </sequential>
  </for>              
</target>

The problem is that ${name} expression gets evaluated only once. Is there another approach to this problem?

役に立ちましたか?

解決

From ant manual basename : "When this task executes, it will set the specified property to the value of the last path element of the specified file"
Properties once set are immutable in vanilla ant, so when using basename task within for loop, the property 'name' holds the value of the first file. Therefore antcontrib var task with unset="true" has to be used :

<target name="store">
 <for param="file">
  <path>
   <fileset dir="." includes="*.xqm"/>
  </path>
  <sequential>
   <var name="name" unset="true"/>
   <basename file="@{file}" property="name" />
   <echo message="@{file}, ${name}"/>
  </sequential>
 </for>              
</target>

Alternatively use local task, when using Ant 1.8.x or later :

<target name="store">
 <for param="file">
  <path>
   <fileset dir="." includes="*.xqm"/>
  </path>
  <sequential>
   <local name="name"/>
   <basename file="@{file}" property="name" />
   <echo message="@{file}, ${name}"/>
  </sequential>
 </for>              
</target>

Finally you may use Ant Flaka instead of antcontrib :

<project xmlns:fl="antlib:it.haefelinger.flaka">
 <fl:install-property-handler />

 <fileset dir="." includes="*.xqm" id="foobar"/>

  <!-- create real file objects and access their properties -->
 <fl:for var="f" in="split('${toString:foobar}', ';')">
  <echo>
  #{  format('filename %s, last modified %tD, size %s bytes', f.tofile.toabs,f.tofile.mtime,f.tofile.size)  }
  </echo>
 </fl:for>

  <!-- simple echoing the basename -->
  <fl:for var="f" in="split('${toString:foobar}', ';')">
   <echo>#{f}</echo>
  </fl:for>  

</project>

他のヒント

If you're averse to using the var task due to Ant's standard of property immutability, there's a way to do this by taking advantage of the fact that normal property references ("${}")and iterated property references ("@{}") can be nested within one another:

<target name="store">
    <for param="file">
        <path>
            <fileset dir="." includes="*.xqm"/>
        </path>
        <sequential>
            <basename file="@{file}" property="@{file}" />
            <echo message="@{file}, ${@{file}}"/>
        </sequential>
    </for>              
</target>

This way, you'll be creating a new property named after each file name.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top