avoid listing directories who's content is never used
diff --git a/WHATSNEW b/WHATSNEW
index 67c8f00..8990ec2 100644
--- a/WHATSNEW
+++ b/WHATSNEW
@@ -44,6 +44,11 @@
  * <ftp> now supports FTPs.
    Github Pull Request #170
 
+ * DirectoryScanner avoids listing directory contents when it known it
+   will never use the information retrieved. This may improve
+   performance in some special cases.
+   Bugzilla Report 66048
+
 Changes from Ant 1.10.11 TO Ant 1.10.12
 =======================================
 
diff --git a/src/main/org/apache/tools/ant/DirectoryScanner.java b/src/main/org/apache/tools/ant/DirectoryScanner.java
index 045fdbf..b7f6479 100644
--- a/src/main/org/apache/tools/ant/DirectoryScanner.java
+++ b/src/main/org/apache/tools/ant/DirectoryScanner.java
@@ -1126,12 +1126,16 @@
     private void processSlowScan(final String[] arr) {
         for (String element : arr) {
             final TokenizedPath path  = new TokenizedPath(element);
-            if (!couldHoldIncluded(path) || contentsExcluded(path)) {
+            if (!scanDuringFastScan(path)) {
                 scandir(new File(basedir, element), path, false);
             }
         }
     }
 
+    private boolean scanDuringFastScan(TokenizedPath path) {
+        return couldHoldIncluded(path) && !contentsExcluded(path);
+    }
+
     /**
      * Scan the given directory for files and directories. Found files and
      * directories are placed in their respective collections, based on the
@@ -1236,7 +1240,18 @@
             final String name = vpath + newFile;
             final TokenizedPath newPath = new TokenizedPath(path, newFile);
             final File file = new File(dir, newFile);
-            final String[] children = file.list();
+            final String[] children;
+
+            // don't invoke file.list() if we know we never use the children
+            if (fast // slow scan scans everything anyway
+                && file.isDirectory() // otherwise we need list() to know whether this is a directory
+                && !scanDuringFastScan(newPath) // otherwise we'd invoke scandir
+                ) {
+                children = new String[0];
+            } else {
+                children = file.list();
+            }
+
             if (children == null || (children.length == 0 && file.isFile())) {
                 if (isIncluded(newPath)) {
                     accountForIncludedFile(newPath, file);
@@ -1263,7 +1278,7 @@
                 } else {
                     everythingIncluded = false;
                     dirsNotIncluded.addElement(name);
-                    if (fast && couldHoldIncluded(newPath) && !contentsExcluded(newPath)) {
+                    if (fast && scanDuringFastScan(newPath)) {
                         scandir(file, newPath, fast, children, directoryNamesFollowed);
                     }
                 }
@@ -1298,7 +1313,7 @@
     private void accountForIncludedDir(final TokenizedPath name, final File file,
                                        final boolean fast) {
         processIncluded(name, file, dirsIncluded, dirsExcluded, dirsDeselected);
-        if (fast && couldHoldIncluded(name) && !contentsExcluded(name)) {
+        if (fast && scanDuringFastScan(name)) {
             scandir(file, name, fast);
         }
     }
@@ -1308,7 +1323,7 @@
                                        final String[] children,
                                        final Deque<String> directoryNamesFollowed) {
         processIncluded(name, file, dirsIncluded, dirsExcluded, dirsDeselected);
-        if (fast && couldHoldIncluded(name) && !contentsExcluded(name)) {
+        if (fast && scanDuringFastScan(name)) {
             scandir(file, name, fast, children, directoryNamesFollowed);
         }
     }
@@ -1319,7 +1334,7 @@
 
     private void accountForNotFollowedSymlink(final TokenizedPath name, final File file) {
         if (!isExcluded(name) && (isIncluded(name)
-                || (file.isDirectory() && couldHoldIncluded(name) && !contentsExcluded(name)))) {
+                || (file.isDirectory() && scanDuringFastScan(name)))) {
             notFollowedSymlinks.add(file.getAbsolutePath());
         }
     }