View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.io.filefilter;
18  
19  import java.io.File;
20  import java.io.FileFilter;
21  import java.io.FilenameFilter;
22  import java.util.Arrays;
23  import java.util.Collections;
24  import java.util.Date;
25  import java.util.HashSet;
26  import java.util.List;
27  import java.util.Objects;
28  import java.util.Set;
29  import java.util.stream.Collector;
30  import java.util.stream.Collectors;
31  import java.util.stream.Stream;
32  import java.util.stream.StreamSupport;
33  
34  import org.apache.commons.io.FileUtils;
35  import org.apache.commons.io.IOCase;
36  
37  /**
38   * Useful utilities for working with file filters. It provides access to most
39   * file filter implementations in this package so you don't have to import
40   * every class you use.
41   *
42   * @since 1.0
43   */
44  public class FileFilterUtils {
45  
46      /* Constructed on demand and then cached */
47      private static final IOFileFilter CVS_FILTER = notFileFilter(
48              and(directoryFileFilter(), nameFileFilter("CVS")));
49  
50  
51      /* Constructed on demand and then cached */
52      private static final IOFileFilter SVN_FILTER = notFileFilter(
53              and(directoryFileFilter(), nameFileFilter(".svn")));
54  
55      /**
56       * Returns a filter that returns true if the file was last modified before
57       * or at the specified cutoff date.
58       *
59       * @param cutoffDate  the time threshold
60       * @return an appropriately configured age file filter
61       * @see AgeFileFilter
62       * @since 1.2
63       */
64      public static IOFileFilter ageFileFilter(final Date cutoffDate) {
65          return new AgeFileFilter(cutoffDate);
66      }
67  
68      /**
69       * Returns a filter that filters files based on a cutoff date.
70       *
71       * @param cutoffDate  the time threshold
72       * @param acceptOlder  if true, older files get accepted, if false, newer
73       * @return an appropriately configured age file filter
74       * @see AgeFileFilter
75       * @since 1.2
76       */
77      public static IOFileFilter ageFileFilter(final Date cutoffDate, final boolean acceptOlder) {
78          return new AgeFileFilter(cutoffDate, acceptOlder);
79      }
80  
81      /**
82       * Returns a filter that returns true if the file was last modified before
83       * or at the same time as the specified reference file.
84       *
85       * @param cutoffReference  the file whose last modification
86       *        time is used as the threshold age of the files
87       * @return an appropriately configured age file filter
88       * @see AgeFileFilter
89       * @since 1.2
90       */
91      public static IOFileFilter ageFileFilter(final File cutoffReference) {
92          return new AgeFileFilter(cutoffReference);
93      }
94  
95      /**
96       * Returns a filter that filters files based on a cutoff reference file.
97       *
98       * @param cutoffReference  the file whose last modification
99       *        time is used as the threshold age of the files
100      * @param acceptOlder  if true, older files get accepted, if false, newer
101      * @return an appropriately configured age file filter
102      * @see AgeFileFilter
103      * @since 1.2
104      */
105     public static IOFileFilter ageFileFilter(final File cutoffReference, final boolean acceptOlder) {
106         return new AgeFileFilter(cutoffReference, acceptOlder);
107     }
108 
109     /**
110      * Returns a filter that returns true if the file was last modified before
111      * or at the specified cutoff time.
112      *
113      * @param cutoffMillis  the time threshold
114      * @return an appropriately configured age file filter
115      * @see AgeFileFilter
116      * @since 1.2
117      */
118     public static IOFileFilter ageFileFilter(final long cutoffMillis) {
119         return new AgeFileFilter(cutoffMillis);
120     }
121 
122     /**
123      * Returns a filter that filters files based on a cutoff time.
124      *
125      * @param cutoffMillis  the time threshold
126      * @param acceptOlder  if true, older files get accepted, if false, newer
127      * @return an appropriately configured age file filter
128      * @see AgeFileFilter
129      * @since 1.2
130      */
131     public static IOFileFilter ageFileFilter(final long cutoffMillis, final boolean acceptOlder) {
132         return new AgeFileFilter(cutoffMillis, acceptOlder);
133     }
134 
135     /**
136      * Returns a filter that ANDs the specified filters.
137      *
138      * @param filters the IOFileFilters that will be ANDed together.
139      * @return a filter that ANDs the specified filters
140      *
141      * @throws IllegalArgumentException if the filters are null or contain a
142      *         null value.
143      * @see AndFileFilter
144      * @since 2.0
145      */
146     public static IOFileFilter and(final IOFileFilter... filters) {
147         return new AndFileFilter(toList(filters));
148     }
149 
150     /**
151      * Returns a filter that ANDs the two specified filters.
152      *
153      * @param filter1  the first filter
154      * @param filter2  the second filter
155      * @return a filter that ANDs the two specified filters
156      * @see #and(IOFileFilter...)
157      * @see AndFileFilter
158      * @deprecated use {@link #and(IOFileFilter...)}
159      */
160     @Deprecated
161     public static IOFileFilter andFileFilter(final IOFileFilter filter1, final IOFileFilter filter2) {
162         return new AndFileFilter(filter1, filter2);
163     }
164 
165     /**
166      * Returns an {@link IOFileFilter} that wraps the
167      * {@link FileFilter} instance.
168      *
169      * @param filter  the filter to be wrapped
170      * @return a new filter that implements IOFileFilter
171      * @see DelegateFileFilter
172      */
173     public static IOFileFilter asFileFilter(final FileFilter filter) {
174         return new DelegateFileFilter(filter);
175     }
176 
177     /**
178      * Returns an {@link IOFileFilter} that wraps the
179      * {@link FilenameFilter} instance.
180      *
181      * @param filter  the filter to be wrapped
182      * @return a new filter that implements IOFileFilter
183      * @see DelegateFileFilter
184      */
185     public static IOFileFilter asFileFilter(final FilenameFilter filter) {
186         return new DelegateFileFilter(filter);
187     }
188 
189     /**
190      * Returns a filter that checks if the file is a directory.
191      *
192      * @return file filter that accepts only directories and not files
193      * @see DirectoryFileFilter#DIRECTORY
194      */
195     public static IOFileFilter directoryFileFilter() {
196         return DirectoryFileFilter.DIRECTORY;
197     }
198 
199     /**
200      * Returns a filter that always returns false.
201      *
202      * @return a false filter
203      * @see FalseFileFilter#FALSE
204      */
205     public static IOFileFilter falseFileFilter() {
206         return FalseFileFilter.FALSE;
207     }
208 
209     /**
210      * Returns a filter that checks if the file is a file (and not a directory).
211      *
212      * @return file filter that accepts only files and not directories
213      * @see FileFileFilter#INSTANCE
214      */
215     public static IOFileFilter fileFileFilter() {
216         return FileFileFilter.INSTANCE;
217     }
218 
219     /**
220      * <p>
221      * Applies an {@link IOFileFilter} to the provided {@link File}
222      * objects. The resulting array is a subset of the original file list that
223      * matches the provided filter.
224      * </p>
225      *
226      * <pre>
227      * Set&lt;File&gt; allFiles = ...
228      * Set&lt;File&gt; javaFiles = FileFilterUtils.filterSet(allFiles,
229      *     FileFilterUtils.suffixFileFilter(".java"));
230      * </pre>
231      * @param filter the filter to apply to the set of files.
232      * @param files the array of files to apply the filter to.
233      *
234      * @return a subset of {@code files} that is accepted by the
235      *         file filter.
236      * @throws NullPointerException if the filter is {@code null}
237      *         or {@code files} contains a {@code null} value.
238      *
239      * @since 2.0
240      */
241     public static File[] filter(final IOFileFilter filter, final File... files) {
242         Objects.requireNonNull(filter, "filter");
243         if (files == null) {
244             return FileUtils.EMPTY_FILE_ARRAY;
245         }
246         return filterFiles(filter, Stream.of(files), Collectors.toList()).toArray(FileUtils.EMPTY_FILE_ARRAY);
247     }
248 
249     /**
250      * <p>
251      * Applies an {@link IOFileFilter} to the provided {@link File}
252      * objects. The resulting array is a subset of the original file list that
253      * matches the provided filter.
254      * </p>
255      *
256      * <p>
257      * The {@link Set} returned by this method is not guaranteed to be thread safe.
258      * </p>
259      *
260      * <pre>
261      * Set&lt;File&gt; allFiles = ...
262      * Set&lt;File&gt; javaFiles = FileFilterUtils.filterSet(allFiles,
263      *     FileFilterUtils.suffixFileFilter(".java"));
264      * </pre>
265      * @param filter the filter to apply to the set of files.
266      * @param files the array of files to apply the filter to.
267      *
268      * @return a subset of {@code files} that is accepted by the
269      *         file filter.
270      * @throws IllegalArgumentException if the filter is {@code null}
271      *         or {@code files} contains a {@code null} value.
272      *
273      * @since 2.0
274      */
275     public static File[] filter(final IOFileFilter filter, final Iterable<File> files) {
276         return filterList(filter, files).toArray(FileUtils.EMPTY_FILE_ARRAY);
277     }
278 
279     /**
280      * <p>
281      * Applies an {@link IOFileFilter} to the provided {@link File} stream and collects the accepted files.
282      * </p>
283      *
284      * @param filter the filter to apply to the stream of files.
285      * @param stream the stream of files on which to apply the filter.
286      * @param collector how to collect the end result.
287      *
288      * @param <R> the return type.
289      * @param <A> the mutable accumulation type of the reduction operation (often hidden as an implementation detail)
290      * @return a subset of files from the stream that is accepted by the filter.
291      * @throws NullPointerException if the filter is {@code null}.
292      */
293     private static <R, A> R filterFiles(final IOFileFilter filter, final Stream<File> stream,
294         final Collector<? super File, A, R> collector) {
295         Objects.requireNonNull(filter, "filter");
296         Objects.requireNonNull(collector, "collector");
297         if (stream == null) {
298             return Stream.<File>empty().collect(collector);
299         }
300         return stream.filter(filter::accept).collect(collector);
301     }
302 
303     /**
304      * <p>
305      * Applies an {@link IOFileFilter} to the provided {@link File}
306      * objects. The resulting list is a subset of the original files that
307      * matches the provided filter.
308      * </p>
309      *
310      * <p>
311      * The {@link List} returned by this method is not guaranteed to be thread safe.
312      * </p>
313      *
314      * <pre>
315      * List&lt;File&gt; filesAndDirectories = ...
316      * List&lt;File&gt; directories = FileFilterUtils.filterList(filesAndDirectories,
317      *     FileFilterUtils.directoryFileFilter());
318      * </pre>
319      * @param filter the filter to apply to each files in the list.
320      * @param files the collection of files to apply the filter to.
321      *
322      * @return a subset of {@code files} that is accepted by the
323      *         file filter.
324      * @throws IllegalArgumentException if the filter is {@code null}
325      *         or {@code files} contains a {@code null} value.
326      * @since 2.0
327      */
328     public static List<File> filterList(final IOFileFilter filter, final File... files) {
329         return Arrays.asList(filter(filter, files));
330     }
331 
332     /**
333      * <p>
334      * Applies an {@link IOFileFilter} to the provided {@link File}
335      * objects. The resulting list is a subset of the original files that
336      * matches the provided filter.
337      * </p>
338      *
339      * <p>
340      * The {@link List} returned by this method is not guaranteed to be thread safe.
341      * </p>
342      *
343      * <pre>
344      * List&lt;File&gt; filesAndDirectories = ...
345      * List&lt;File&gt; directories = FileFilterUtils.filterList(filesAndDirectories,
346      *     FileFilterUtils.directoryFileFilter());
347      * </pre>
348      * @param filter the filter to apply to each files in the list.
349      * @param files the collection of files to apply the filter to.
350      *
351      * @return a subset of {@code files} that is accepted by the
352      *         file filter.
353      * @throws IllegalArgumentException if the filter is {@code null}
354      * @since 2.0
355      */
356     public static List<File> filterList(final IOFileFilter filter, final Iterable<File> files) {
357         if (files == null) {
358             return Collections.emptyList();
359         }
360         return filterFiles(filter, StreamSupport.stream(files.spliterator(), false), Collectors.toList());
361     }
362 
363     /**
364      * <p>
365      * Applies an {@link IOFileFilter} to the provided {@link File}
366      * objects. The resulting set is a subset of the original file list that
367      * matches the provided filter.
368      * </p>
369      *
370      * <p>
371      * The {@link Set} returned by this method is not guaranteed to be thread safe.
372      * </p>
373      *
374      * <pre>
375      * Set&lt;File&gt; allFiles = ...
376      * Set&lt;File&gt; javaFiles = FileFilterUtils.filterSet(allFiles,
377      *     FileFilterUtils.suffixFileFilter(".java"));
378      * </pre>
379      * @param filter the filter to apply to the set of files.
380      * @param files the collection of files to apply the filter to.
381      *
382      * @return a subset of {@code files} that is accepted by the
383      *         file filter.
384      * @throws IllegalArgumentException if the filter is {@code null}
385      *         or {@code files} contains a {@code null} value.
386      *
387      * @since 2.0
388      */
389     public static Set<File> filterSet(final IOFileFilter filter, final File... files) {
390         return new HashSet<>(Arrays.asList(filter(filter, files)));
391     }
392 
393     /**
394      * <p>
395      * Applies an {@link IOFileFilter} to the provided {@link File}
396      * objects. The resulting set is a subset of the original file list that
397      * matches the provided filter.
398      * </p>
399      *
400      * <p>
401      * The {@link Set} returned by this method is not guaranteed to be thread safe.
402      * </p>
403      *
404      * <pre>
405      * Set&lt;File&gt; allFiles = ...
406      * Set&lt;File&gt; javaFiles = FileFilterUtils.filterSet(allFiles,
407      *     FileFilterUtils.suffixFileFilter(".java"));
408      * </pre>
409      * @param filter the filter to apply to the set of files.
410      * @param files the collection of files to apply the filter to.
411      *
412      * @return a subset of {@code files} that is accepted by the
413      *         file filter.
414      * @throws IllegalArgumentException if the filter is {@code null}
415      *
416      * @since 2.0
417      */
418     public static Set<File> filterSet(final IOFileFilter filter, final Iterable<File> files) {
419         if (files == null) {
420             return Collections.emptySet();
421         }
422         return filterFiles(filter, StreamSupport.stream(files.spliterator(), false), Collectors.toSet());
423     }
424 
425     /**
426      * Returns a filter that accepts files that begin with the provided magic
427      * number.
428      *
429      * @param magicNumber the magic number (byte sequence) to match at the
430      *        beginning of each file.
431      *
432      * @return an IOFileFilter that accepts files beginning with the provided
433      *         magic number.
434      *
435      * @throws IllegalArgumentException if {@code magicNumber} is
436      *         {@code null} or is of length zero.
437      * @see MagicNumberFileFilter
438      * @since 2.0
439      */
440     public static IOFileFilter magicNumberFileFilter(final byte[] magicNumber) {
441         return new MagicNumberFileFilter(magicNumber);
442     }
443 
444     /**
445      * Returns a filter that accepts files that contains the provided magic
446      * number at a specified offset within the file.
447      *
448      * @param magicNumber the magic number (byte sequence) to match at the
449      *        provided offset in each file.
450      * @param offset the offset within the files to look for the magic number.
451      *
452      * @return an IOFileFilter that accepts files containing the magic number
453      *         at the specified offset.
454      *
455      * @throws IllegalArgumentException if {@code magicNumber} is
456      *         {@code null}, or contains no bytes, or {@code offset}
457      *         is a negative number.
458      * @see MagicNumberFileFilter
459      * @since 2.0
460      */
461     public static IOFileFilter magicNumberFileFilter(final byte[] magicNumber, final long offset) {
462         return new MagicNumberFileFilter(magicNumber, offset);
463     }
464 
465     /**
466      * Returns a filter that accepts files that begin with the provided magic
467      * number.
468      *
469      * @param magicNumber the magic number (byte sequence) to match at the
470      *        beginning of each file.
471      *
472      * @return an IOFileFilter that accepts files beginning with the provided
473      *         magic number.
474      *
475      * @throws IllegalArgumentException if {@code magicNumber} is
476      *         {@code null} or the empty String.
477      * @see MagicNumberFileFilter
478      * @since 2.0
479      */
480     public static IOFileFilter magicNumberFileFilter(final String magicNumber) {
481         return new MagicNumberFileFilter(magicNumber);
482     }
483 
484     /**
485      * Returns a filter that accepts files that contains the provided magic
486      * number at a specified offset within the file.
487      *
488      * @param magicNumber the magic number (byte sequence) to match at the
489      *        provided offset in each file.
490      * @param offset the offset within the files to look for the magic number.
491      *
492      * @return an IOFileFilter that accepts files containing the magic number
493      *         at the specified offset.
494      *
495      * @throws IllegalArgumentException if {@code magicNumber} is
496      *         {@code null} or the empty String, or if offset is a
497      *         negative number.
498      * @see MagicNumberFileFilter
499      * @since 2.0
500      */
501     public static IOFileFilter magicNumberFileFilter(final String magicNumber, final long offset) {
502         return new MagicNumberFileFilter(magicNumber, offset);
503     }
504 
505     /**
506      * Decorates a filter to make it ignore CVS directories.
507      * Passing in {@code null} will return a filter that accepts everything
508      * except CVS directories.
509      *
510      * @param filter  the filter to decorate, null means an unrestricted filter
511      * @return the decorated filter, never null
512      * @since 1.1 (method existed but had a bug in 1.0)
513      */
514     public static IOFileFilter makeCVSAware(final IOFileFilter filter) {
515         return filter == null ? CVS_FILTER : and(filter, CVS_FILTER);
516     }
517 
518     /**
519      * Decorates a filter so that it only applies to directories and not to files.
520      *
521      * @param filter  the filter to decorate, null means an unrestricted filter
522      * @return the decorated filter, never null
523      * @see DirectoryFileFilter#DIRECTORY
524      * @since 1.3
525      */
526     public static IOFileFilter makeDirectoryOnly(final IOFileFilter filter) {
527         if (filter == null) {
528             return DirectoryFileFilter.DIRECTORY;
529         }
530         return DirectoryFileFilter.DIRECTORY.and(filter);
531     }
532 
533     /**
534      * Decorates a filter so that it only applies to files and not to directories.
535      *
536      * @param filter  the filter to decorate, null means an unrestricted filter
537      * @return the decorated filter, never null
538      * @see FileFileFilter#INSTANCE
539      * @since 1.3
540      */
541     public static IOFileFilter makeFileOnly(final IOFileFilter filter) {
542         if (filter == null) {
543             return FileFileFilter.INSTANCE;
544         }
545         return FileFileFilter.INSTANCE.and(filter);
546     }
547 
548     /**
549      * Decorates a filter to make it ignore SVN directories.
550      * Passing in {@code null} will return a filter that accepts everything
551      * except SVN directories.
552      *
553      * @param filter  the filter to decorate, null means an unrestricted filter
554      * @return the decorated filter, never null
555      * @since 1.1
556      */
557     public static IOFileFilter makeSVNAware(final IOFileFilter filter) {
558         return filter == null ? SVN_FILTER : and(filter, SVN_FILTER);
559     }
560 
561     /**
562      * Returns a filter that returns true if the file name matches the specified text.
563      *
564      * @param name  the file name
565      * @return a name checking filter
566      * @see NameFileFilter
567      */
568     public static IOFileFilter nameFileFilter(final String name) {
569         return new NameFileFilter(name);
570     }
571 
572     /**
573      * Returns a filter that returns true if the file name matches the specified text.
574      *
575      * @param name  the file name
576      * @param ioCase  how to handle case sensitivity, null means case-sensitive
577      * @return a name checking filter
578      * @see NameFileFilter
579      * @since 2.0
580      */
581     public static IOFileFilter nameFileFilter(final String name, final IOCase ioCase) {
582         return new NameFileFilter(name, ioCase);
583     }
584 
585     /**
586      * Returns a filter that NOTs the specified filter.
587      *
588      * @param filter  the filter to invert
589      * @return a filter that NOTs the specified filter
590      * @see NotFileFilter
591      */
592     public static IOFileFilter notFileFilter(final IOFileFilter filter) {
593         return filter.negate();
594     }
595 
596     /**
597      * Returns a filter that ORs the specified filters.
598      *
599      * @param filters the IOFileFilters that will be ORed together.
600      * @return a filter that ORs the specified filters
601      *
602      * @throws IllegalArgumentException if the filters are null or contain a
603      *         null value.
604      * @see OrFileFilter
605      * @since 2.0
606      */
607     public static IOFileFilter or(final IOFileFilter... filters) {
608         return new OrFileFilter(toList(filters));
609     }
610 
611     /**
612      * Returns a filter that ORs the two specified filters.
613      *
614      * @param filter1  the first filter
615      * @param filter2  the second filter
616      * @return a filter that ORs the two specified filters
617      * @see #or(IOFileFilter...)
618      * @see OrFileFilter
619      * @deprecated use {@link #or(IOFileFilter...)}
620      */
621     @Deprecated
622     public static IOFileFilter orFileFilter(final IOFileFilter filter1, final IOFileFilter filter2) {
623         return new OrFileFilter(filter1, filter2);
624     }
625 
626     /**
627      * Returns a filter that returns true if the file name starts with the specified text.
628      *
629      * @param prefix  the file name prefix
630      * @return a prefix checking filter
631      * @see PrefixFileFilter
632      */
633     public static IOFileFilter prefixFileFilter(final String prefix) {
634         return new PrefixFileFilter(prefix);
635     }
636 
637     /**
638      * Returns a filter that returns true if the file name starts with the specified text.
639      *
640      * @param prefix  the file name prefix
641      * @param ioCase  how to handle case sensitivity, null means case-sensitive
642      * @return a prefix checking filter
643      * @see PrefixFileFilter
644      * @since 2.0
645      */
646     public static IOFileFilter prefixFileFilter(final String prefix, final IOCase ioCase) {
647         return new PrefixFileFilter(prefix, ioCase);
648     }
649 
650     /**
651      * Returns a filter that returns true if the file is bigger than a certain size.
652      *
653      * @param threshold  the file size threshold
654      * @return an appropriately configured SizeFileFilter
655      * @see SizeFileFilter
656      * @since 1.2
657      */
658     public static IOFileFilter sizeFileFilter(final long threshold) {
659         return new SizeFileFilter(threshold);
660     }
661 
662     /**
663      * Returns a filter that filters based on file size.
664      *
665      * @param threshold  the file size threshold
666      * @param acceptLarger  if true, larger files get accepted, if false, smaller
667      * @return an appropriately configured SizeFileFilter
668      * @see SizeFileFilter
669      * @since 1.2
670      */
671     public static IOFileFilter sizeFileFilter(final long threshold, final boolean acceptLarger) {
672         return new SizeFileFilter(threshold, acceptLarger);
673     }
674 
675     /**
676      * Returns a filter that accepts files whose size is &gt;= minimum size
677      * and &lt;= maximum size.
678      *
679      * @param minSizeInclusive the minimum file size (inclusive)
680      * @param maxSizeInclusive the maximum file size (inclusive)
681      * @return an appropriately configured IOFileFilter
682      * @see SizeFileFilter
683      * @since 1.3
684      */
685     public static IOFileFilter sizeRangeFileFilter(final long minSizeInclusive, final long maxSizeInclusive ) {
686         final IOFileFilter minimumFilter = new SizeFileFilter(minSizeInclusive, true);
687         final IOFileFilter maximumFilter = new SizeFileFilter(maxSizeInclusive + 1L, false);
688         return minimumFilter.and(maximumFilter);
689     }
690 
691     /**
692      * Returns a filter that returns true if the file name ends with the specified text.
693      *
694      * @param suffix  the file name suffix
695      * @return a suffix checking filter
696      * @see SuffixFileFilter
697      */
698     public static IOFileFilter suffixFileFilter(final String suffix) {
699         return new SuffixFileFilter(suffix);
700     }
701 
702     /**
703      * Returns a filter that returns true if the file name ends with the specified text.
704      *
705      * @param suffix  the file name suffix
706      * @param ioCase  how to handle case sensitivity, null means case-sensitive
707      * @return a suffix checking filter
708      * @see SuffixFileFilter
709      * @since 2.0
710      */
711     public static IOFileFilter suffixFileFilter(final String suffix, final IOCase ioCase) {
712         return new SuffixFileFilter(suffix, ioCase);
713     }
714 
715     /**
716      * Create a List of file filters.
717      *
718      * @param filters The file filters
719      * @return The list of file filters
720      * @throws NullPointerException if the filters are null or contain a
721      *         null value.
722      * @since 2.0
723      */
724     public static List<IOFileFilter> toList(final IOFileFilter... filters) {
725         return Stream.of(Objects.requireNonNull(filters, "filters")).map(Objects::requireNonNull).collect(Collectors.toList());
726     }
727 
728     /**
729      * Returns a filter that always returns true.
730      *
731      * @return a true filter
732      * @see TrueFileFilter#TRUE
733      */
734     public static IOFileFilter trueFileFilter() {
735         return TrueFileFilter.TRUE;
736     }
737 
738     /**
739      * FileFilterUtils is not normally instantiated.
740      */
741     public FileFilterUtils() {
742     }
743 
744 }