Skip to content

Commit 642d659

Browse files
committed
IO-173 FileUtils.listFiles() doesn't return directories
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/io/trunk@1295700 13f79535-47bb-0310-9956-ffa450edef68
1 parent 4cef529 commit 642d659

3 files changed

Lines changed: 153 additions & 16 deletions

File tree

src/changes/changes.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ The <action> type attribute can be add,update,fix,remove.
4040

4141
<body>
4242
<release version="2.2" date="TBA">
43+
<action dev="sebb" type="add" issue="IO-173" due-to="Marcos Vinícius da Silva">
44+
FileUtils.listFiles() doesn't return directories
45+
</action>
4346
<action dev="sebb" type="fix" issue="IO-276" due-to="nkami">
4447
"FileUtils#deleteDirectoryOnExit(File)" does not work
4548
</action>

src/main/java/org/apache/commons/io/FileUtils.java

Lines changed: 89 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -415,14 +415,19 @@ public static File[] convertFileCollectionToFileArray(Collection<File> files) {
415415
* @param files the collection of files found.
416416
* @param directory the directory to search in.
417417
* @param filter the filter to apply to files and directories.
418+
* @param includeSubDirectories indicates if will include the subdirectories themselves
418419
*/
419420
private static void innerListFiles(Collection<File> files, File directory,
420-
IOFileFilter filter) {
421+
IOFileFilter filter, boolean includeSubDirectories) {
421422
File[] found = directory.listFiles((FileFilter) filter);
423+
422424
if (found != null) {
423425
for (File file : found) {
424426
if (file.isDirectory()) {
425-
innerListFiles(files, file, filter);
427+
if (includeSubDirectories) {
428+
files.add(file);
429+
}
430+
innerListFiles(files, file, filter, includeSubDirectories);
426431
} else {
427432
files.add(file);
428433
}
@@ -457,31 +462,76 @@ private static void innerListFiles(Collection<File> files, File directory,
457462
*/
458463
public static Collection<File> listFiles(
459464
File directory, IOFileFilter fileFilter, IOFileFilter dirFilter) {
460-
if (!directory.isDirectory()) {
461-
throw new IllegalArgumentException(
462-
"Parameter 'directory' is not a directory");
463-
}
464-
if (fileFilter == null) {
465-
throw new NullPointerException("Parameter 'fileFilter' is null");
466-
}
465+
validateListFilesParameters(directory, fileFilter);
466+
467+
IOFileFilter effFileFilter = setupEfectiveFileFilter(fileFilter);
468+
IOFileFilter effDirFilter = setupEffectiveDirFilter(dirFilter);
469+
470+
//Find files
471+
Collection<File> files = new java.util.LinkedList<File>();
472+
innerListFiles(files, directory,
473+
FileFilterUtils.or(effFileFilter, effDirFilter), false);
474+
return files;
475+
}
476+
477+
private static void validateListFilesParameters(File directory,
478+
IOFileFilter fileFilter) {
479+
if (!directory.isDirectory()) {
480+
throw new IllegalArgumentException(
481+
"Parameter 'directory' is not a directory");
482+
}
483+
if (fileFilter == null) {
484+
throw new NullPointerException("Parameter 'fileFilter' is null");
485+
}
486+
}
467487

468-
//Setup effective file filter
469-
IOFileFilter effFileFilter = FileFilterUtils.and(fileFilter,
470-
FileFilterUtils.notFileFilter(DirectoryFileFilter.INSTANCE));
488+
private static IOFileFilter setupEfectiveFileFilter(IOFileFilter fileFilter) {
489+
return FileFilterUtils.and(fileFilter,
490+
FileFilterUtils.notFileFilter(DirectoryFileFilter.INSTANCE));
491+
}
471492

472-
//Setup effective directory filter
473-
IOFileFilter effDirFilter;
493+
private static IOFileFilter setupEffectiveDirFilter(IOFileFilter dirFilter) {
494+
IOFileFilter effDirFilter;
474495
if (dirFilter == null) {
475496
effDirFilter = FalseFileFilter.INSTANCE;
476497
} else {
477498
effDirFilter = FileFilterUtils.and(dirFilter,
478499
DirectoryFileFilter.INSTANCE);
479500
}
501+
return effDirFilter;
502+
}
503+
504+
/**
505+
* Finds files within a given directory (and optionally its
506+
* subdirectories). All files found are filtered by an IOFileFilter.
507+
* <p>
508+
* The resulting collection includes the subdirectories themselves.
509+
* <p>
510+
* @see org.apache.commons.io.FileUtils#listFiles
511+
*
512+
* @param directory the directory to search in
513+
* @param fileFilter filter to apply when finding files.
514+
* @param dirFilter optional filter to apply when finding subdirectories.
515+
* If this parameter is <code>null</code>, subdirectories will not be included in the
516+
* search. Use TrueFileFilter.INSTANCE to match all directories.
517+
* @return an collection of java.io.File with the matching files
518+
* @see org.apache.commons.io.filefilter.FileFilterUtils
519+
* @see org.apache.commons.io.filefilter.NameFileFilter
520+
*/
521+
public static Collection<File> listFilesAndDirs(
522+
File directory, IOFileFilter fileFilter, IOFileFilter dirFilter) {
523+
validateListFilesParameters(directory, fileFilter);
524+
525+
IOFileFilter effFileFilter = setupEfectiveFileFilter(fileFilter);
526+
IOFileFilter effDirFilter = setupEffectiveDirFilter(dirFilter);
480527

481528
//Find files
482529
Collection<File> files = new java.util.LinkedList<File>();
530+
if (directory.isDirectory()) {
531+
files.add(directory);
532+
}
483533
innerListFiles(files, directory,
484-
FileFilterUtils.or(effFileFilter, effDirFilter));
534+
FileFilterUtils.or(effFileFilter, effDirFilter), true);
485535
return files;
486536
}
487537

@@ -508,6 +558,30 @@ public static Iterator<File> iterateFiles(
508558
return listFiles(directory, fileFilter, dirFilter).iterator();
509559
}
510560

561+
/**
562+
* Allows iteration over the files in given directory (and optionally
563+
* its subdirectories).
564+
* <p>
565+
* All files found are filtered by an IOFileFilter. This method is
566+
* based on {@link #listFilesAndDirs(File, IOFileFilter, IOFileFilter)},
567+
* which supports Iterable ('foreach' loop).
568+
* <p>
569+
* The resulting iterator includes the subdirectories themselves.
570+
*
571+
* @param directory the directory to search in
572+
* @param fileFilter filter to apply when finding files.
573+
* @param dirFilter optional filter to apply when finding subdirectories.
574+
* If this parameter is <code>null</code>, subdirectories will not be included in the
575+
* search. Use TrueFileFilter.INSTANCE to match all directories.
576+
* @return an iterator of java.io.File for the matching files
577+
* @see org.apache.commons.io.filefilter.FileFilterUtils
578+
* @see org.apache.commons.io.filefilter.NameFileFilter
579+
*/
580+
public static Iterator<File> iterateFilesAndDirs(
581+
File directory, IOFileFilter fileFilter, IOFileFilter dirFilter) {
582+
return listFilesAndDirs(directory, fileFilter, dirFilter).iterator();
583+
}
584+
511585
//-----------------------------------------------------------------------
512586
/**
513587
* Converts an array of file extensions to suffixes for use

src/test/java/org/apache/commons/io/FileUtilsTestCase.java

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1345,6 +1345,9 @@ public void testListFiles() throws Exception {
13451345
File subDir = new File(srcDir, "list_test" );
13461346
subDir.mkdir();
13471347

1348+
File subDir2 = new File(subDir, "subdir" );
1349+
subDir2.mkdir();
1350+
13481351
String[] fileNames = {"a.txt", "b.txt", "c.txt", "d.txt", "e.txt", "f.txt"};
13491352
int[] fileSizes = {123, 234, 345, 456, 678, 789};
13501353

@@ -1360,7 +1363,7 @@ public void testListFiles() throws Exception {
13601363
int count = files.size();
13611364
Object[] fileObjs = files.toArray();
13621365

1363-
assertEquals(files.size(), fileNames.length);
1366+
assertEquals(fileNames.length, files.size());
13641367

13651368
Map<String, String> foundFileNames = new HashMap<String, String>();
13661369

@@ -1378,6 +1381,33 @@ public void testListFiles() throws Exception {
13781381

13791382
subDir.delete();
13801383
}
1384+
1385+
public void testListFilesWithDirs() throws IOException {
1386+
File srcDir = getTestDirectory();
1387+
1388+
File subDir1 = new File(srcDir, "subdir");
1389+
subDir1.mkdir();
1390+
1391+
File subDir2 = new File(subDir1, "subdir2");
1392+
subDir2.mkdir();
1393+
1394+
File someFile = new File(subDir2, "a.txt");
1395+
createFile(someFile, 100);
1396+
1397+
File subDir3 = new File(subDir2, "subdir3");
1398+
subDir3.mkdir();
1399+
1400+
Collection<File> files = FileUtils.listFilesAndDirs(subDir1,
1401+
new WildcardFileFilter("*.*"), new WildcardFileFilter("*"));
1402+
1403+
assertEquals(4, files.size());
1404+
assertTrue("Should contain the directory.", files.contains(subDir1));
1405+
assertTrue("Should contain the directory.", files.contains(subDir2));
1406+
assertTrue("Should contain the file.", files.contains(someFile));
1407+
assertTrue("Should contain the directory.", files.contains(subDir3));
1408+
1409+
subDir1.delete();
1410+
}
13811411

13821412
public void testIterateFiles() throws Exception {
13831413
File srcDir = getTestDirectory();
@@ -1414,6 +1444,36 @@ public void testIterateFiles() throws Exception {
14141444

14151445
subDir.delete();
14161446
}
1447+
1448+
public void testIterateFilesAndDirs() throws IOException {
1449+
File srcDir = getTestDirectory();
1450+
1451+
File subDir1 = new File(srcDir, "subdir");
1452+
subDir1.mkdir();
1453+
1454+
File subDir2 = new File(subDir1, "subdir2");
1455+
subDir2.mkdir();
1456+
1457+
File someFile = new File(subDir2, "a.txt");
1458+
createFile(someFile, 100);
1459+
1460+
File subDir3 = new File(subDir2, "subdir3");
1461+
subDir3.mkdir();
1462+
1463+
Collection<File> filesAndDirs = Arrays.asList(subDir1, subDir2, someFile, subDir3);
1464+
1465+
int filesCount = 0;
1466+
Iterator<File> files = FileUtils.iterateFilesAndDirs(subDir1,
1467+
new WildcardFileFilter("*.*"),
1468+
new WildcardFileFilter("*"));
1469+
while (files.hasNext()) {
1470+
filesCount++;
1471+
File file = files.next();
1472+
assertTrue("Should contain the directory/file", filesAndDirs.contains(file));
1473+
}
1474+
1475+
assertEquals(filesCount, filesAndDirs.size());
1476+
}
14171477

14181478
public void testReadFileToStringWithDefaultEncoding() throws Exception {
14191479
File file = new File(getTestDirectory(), "read.obj");

0 commit comments

Comments
 (0)