Если файлы могут быть добавлены или изменены только в наблюдаемом каталоге, вы можете использовать эту простую задачу OutOfDate из antcontrib.
<property name="watched-dir.flagfile"
location="MUST be not in watched dir"/>
<outofdate>
<sourcefiles>
<fileset dir="watched-dir"/>
</sourcefiles>
<targetfiles>
<pathelement location="${watched-dir.flagfile}"/>
</targetfiles>
<sequential>
<!--Tasks when something changes go here-->
<touch file="${watched-dir.flagfile}"/>
</sequential>
</outofdate>
Если файлы могут исчезнуть из наблюдаемого каталога, у вас есть более сложная проблема, которую вы можете решить, создав теневую структуру каталогов наблюдаемого каталога и проверив, соответствует ли она наблюдаемому каталогу. Это более сложное задание, но я дам вам сценарий для создания теневого каталога, поскольку он не прост:
<property name="TALK" value="true"/>
<property name="shadow-dir"
location="MUST be not in watched dir"/>
<touch
mkdirs="true"
verbose="${TALK}"
>
<fileset dir="watched-dir">
<patterns/>
<type type="file"/>
</fileset>
<!-- That's the tricky globmapper to make touch task work -->
<globmapper from="*" to="${shadow-dir}/*"/>
</touch>
<!--
Due to how touch task with mapped fileset is implemented, it
truncates file access times down to a milliseconds, so if you
would have used outofdate task on shadow dir it would always
show that something is out of date.
Because of that, touching all files in ${shadow-dir} again fixes
that chicken and egg problem.
-->
<touch verbose="${TALK}">
<fileset dir="${shadow-dir}"/>
</touch>
С созданием теневого каталога я оставлю задачу проверки согласованности каталогов в качестве упражнения для читателя.