diff --git a/source/net/filebot/cli/ArgumentBean.java b/source/net/filebot/cli/ArgumentBean.java index f984b935..f09589a0 100644 --- a/source/net/filebot/cli/ArgumentBean.java +++ b/source/net/filebot/cli/ArgumentBean.java @@ -160,9 +160,9 @@ public class ArgumentBean { if (resolveFolders && file.isDirectory()) { if (recursive) { - files.addAll(listFiles(file)); + files.addAll(listFiles(file, FILES)); } else { - files.addAll(filter(getChildren(file, FILES), NOT_HIDDEN)); + files.addAll(getChildren(file, FILES)); } } else { files.add(file); diff --git a/source/net/filebot/cli/FolderWatchService.java b/source/net/filebot/cli/FolderWatchService.java index 245f7644..f518047e 100644 --- a/source/net/filebot/cli/FolderWatchService.java +++ b/source/net/filebot/cli/FolderWatchService.java @@ -145,7 +145,7 @@ public abstract class FolderWatchService implements Closeable { // start watching newly created folder if (watchTree) { try { - commitSet.addAll(listFiles(file)); + commitSet.addAll(listFiles(file, FILES)); watchFolder(file); } catch (IOException e) { debug.log(Level.SEVERE, e.getMessage(), e); diff --git a/source/net/filebot/cli/ScriptShellBaseClass.java b/source/net/filebot/cli/ScriptShellBaseClass.java index b370b73c..d78ec41e 100644 --- a/source/net/filebot/cli/ScriptShellBaseClass.java +++ b/source/net/filebot/cli/ScriptShellBaseClass.java @@ -4,6 +4,7 @@ import static java.util.Arrays.*; import static java.util.Collections.*; import static net.filebot.Logging.*; import static net.filebot.media.XattrMetaInfo.*; +import static net.filebot.util.FileUtilities.*; import static net.filebot.util.StringUtilities.*; import java.io.BufferedReader; @@ -46,7 +47,6 @@ import net.filebot.WebServices; import net.filebot.format.AssociativeScriptObject; import net.filebot.media.MediaDetection; import net.filebot.similarity.SeasonEpisodeMatcher.SxE; -import net.filebot.util.FileUtilities; import net.filebot.web.Movie; public abstract class ScriptShellBaseClass extends Script { @@ -95,7 +95,7 @@ public abstract class ScriptShellBaseClass extends Script { } public Object executeScript(String input, Map bindings, Object... args) throws Throwable { - return executeScript(input, asList(getArgumentBean().getArray()), bindings, FileUtilities.asFileList(args)); + return executeScript(input, asList(getArgumentBean().getArray()), bindings, asFileList(args)); } public Object executeScript(String input, List argv, Map bindings, List args) throws Throwable { @@ -212,7 +212,7 @@ public abstract class ScriptShellBaseClass extends Script { } public String detectSeriesName(Object files, boolean anime) throws Exception { - List input = FileUtilities.asFileList(files); + List input = asFileList(files); if (input.isEmpty()) return null; @@ -425,7 +425,7 @@ public abstract class ScriptShellBaseClass extends Script { } public List getMediaInfo(Collection files, String format) throws Exception { - return cli.getMediaInfo(FileUtilities.asFileList(files), format, null); // explicitly ignore the --filter option + return cli.getMediaInfo(asFileList(files), format, null); // explicitly ignore the --filter option } public Object getMediaInfo(Map parameters) throws Exception { @@ -453,12 +453,12 @@ public abstract class ScriptShellBaseClass extends Script { private List getInputFileList(Map parameters) { Object file = parameters.get("file"); if (file != null) { - return FileUtilities.asFileList(file); + return asFileList(file); } Object folder = parameters.get("folder"); if (folder != null) { - return FileUtilities.listFiles(FileUtilities.asFileList(folder), 0, false, true, false); + return listFiles(asFileList(folder), 0, FILES, HUMAN_ORDER); } return emptyList(); @@ -469,8 +469,8 @@ public abstract class ScriptShellBaseClass extends Script { Map files = new LinkedHashMap(); if (map != null) { for (Entry it : map.entrySet()) { - List key = FileUtilities.asFileList(it.getKey()); - List value = FileUtilities.asFileList(it.getValue()); + List key = asFileList(it.getKey()); + List value = asFileList(it.getValue()); if (key.size() == 1 && value.size() == 1) { files.put(key.get(0), value.get(0)); } else { diff --git a/source/net/filebot/cli/ScriptShellMethods.java b/source/net/filebot/cli/ScriptShellMethods.java index 73877f8d..e92424d7 100644 --- a/source/net/filebot/cli/ScriptShellMethods.java +++ b/source/net/filebot/cli/ScriptShellMethods.java @@ -6,6 +6,7 @@ import static java.util.Collections.*; import static java.util.stream.Collectors.*; import static net.filebot.MediaTypes.*; import static net.filebot.media.XattrMetaInfo.*; +import static net.filebot.util.FileUtilities.*; import java.io.File; import java.io.IOException; @@ -117,7 +118,7 @@ public class ScriptShellMethods { } public static List listTree(File self, int maxDepth) { - return FileUtilities.listFiles(singleton(self), maxDepth, false, true, true); + return FileUtilities.listFiles(singleton(self), maxDepth, FILES, HUMAN_ORDER); } public static List getFiles(File self) { @@ -125,7 +126,7 @@ public class ScriptShellMethods { } public static List getFiles(File self, Closure closure) { - return getFiles(singletonList(self), closure); + return getFiles(singleton(self), closure); } public static List getFiles(Collection self) { @@ -133,14 +134,14 @@ public class ScriptShellMethods { } public static List getFiles(Collection self, Closure closure) { - final List roots = FileUtilities.asFileList(self.toArray()); + List roots = FileUtilities.asFileList(self.toArray()); - List files = FileUtilities.listFiles(roots); + List files = FileUtilities.listFiles(roots, FILES, HUMAN_ORDER); if (closure != null) { files = DefaultGroovyMethods.findAll(files, closure); } - return FileUtilities.sortByUniquePath(files); + return files; } public static List getFolders(File self) { @@ -156,14 +157,14 @@ public class ScriptShellMethods { } public static List getFolders(Collection self, Closure closure) { - final List roots = FileUtilities.asFileList(self.toArray()); + List roots = FileUtilities.asFileList(self.toArray()); - List folders = FileUtilities.listFolders(roots); + List folders = FileUtilities.listFolders(roots, HUMAN_ORDER); if (closure != null) { folders = DefaultGroovyMethods.findAll(folders, closure); } - return FileUtilities.sortByUniquePath(folders); + return folders; } public static List getMediaFolders(File self) throws IOException { diff --git a/source/net/filebot/format/MediaBindingBean.java b/source/net/filebot/format/MediaBindingBean.java index e5963e1d..002b622e 100644 --- a/source/net/filebot/format/MediaBindingBean.java +++ b/source/net/filebot/format/MediaBindingBean.java @@ -34,8 +34,6 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Objects; import java.util.Optional; -import java.util.SortedSet; -import java.util.TreeSet; import java.util.regex.Pattern; import com.cedarsoftware.util.io.JsonWriter; @@ -992,9 +990,9 @@ public class MediaBindingBean { public File getInferredMediaFile() { if (getMediaFile().isDirectory()) { // just select the first video file in the folder as media sample - SortedSet videos = new TreeSet(filter(listFiles(getMediaFile()), VIDEO_FILES)); + List videos = listFiles(getMediaFile(), VIDEO_FILES, CASE_INSENSITIVE_ORDER); if (videos.size() > 0) { - return videos.iterator().next(); + return videos.get(0); } } else if (SUBTITLE_FILES.accept(getMediaFile()) || ((infoObject instanceof Episode || infoObject instanceof Movie) && !VIDEO_FILES.accept(getMediaFile()))) { // prefer equal match from current context if possible diff --git a/source/net/filebot/media/MediaDetection.java b/source/net/filebot/media/MediaDetection.java index 5285a2fd..2de30784 100644 --- a/source/net/filebot/media/MediaDetection.java +++ b/source/net/filebot/media/MediaDetection.java @@ -1204,7 +1204,7 @@ public class MediaDetection { Set collection = new LinkedHashSet(); List nfoFiles = new ArrayList(); if (file.isDirectory()) { - nfoFiles.addAll(filter(listFiles(file), NFO_FILES)); + nfoFiles.addAll(listFiles(file, NFO_FILES)); } else if (file.getParentFile() != null && file.getParentFile().isDirectory()) { nfoFiles.addAll(getChildren(file.getParentFile(), NFO_FILES)); } diff --git a/source/net/filebot/ui/filter/AttributeTool.java b/source/net/filebot/ui/filter/AttributeTool.java index 6ee865ec..4ad7d0d4 100644 --- a/source/net/filebot/ui/filter/AttributeTool.java +++ b/source/net/filebot/ui/filter/AttributeTool.java @@ -55,8 +55,7 @@ class AttributeTool extends Tool { return model; } - List files = filter(listFiles(root), VIDEO_FILES, SUBTITLE_FILES); - files.sort(HUMAN_ORDER); + List files = listFiles(root, filter(VIDEO_FILES, SUBTITLE_FILES), HUMAN_ORDER); for (File file : files) { Object metaObject = xattr.getMetaInfo(file); diff --git a/source/net/filebot/ui/filter/ExtractTool.java b/source/net/filebot/ui/filter/ExtractTool.java index 04041dbe..8144b60b 100644 --- a/source/net/filebot/ui/filter/ExtractTool.java +++ b/source/net/filebot/ui/filter/ExtractTool.java @@ -82,9 +82,7 @@ class ExtractTool extends Tool { } // ignore non-archives files and trailing multi-volume parts - List files = filter(listFiles(root), Archive.VOLUME_ONE_FILTER); - files.sort(HUMAN_ORDER); - + List files = listFiles(root, Archive.VOLUME_ONE_FILTER, HUMAN_ORDER); List entries = new ArrayList(); try { diff --git a/source/net/filebot/ui/filter/MediaInfoTool.java b/source/net/filebot/ui/filter/MediaInfoTool.java index 9e8ae26f..582c70d6 100644 --- a/source/net/filebot/ui/filter/MediaInfoTool.java +++ b/source/net/filebot/ui/filter/MediaInfoTool.java @@ -58,9 +58,7 @@ class MediaInfoTool extends Tool { return new MediaInfoTableModel(); } - List files = filter(listFiles(root), VIDEO_FILES, AUDIO_FILES); - files.sort(HUMAN_ORDER); - + List files = listFiles(root, filter(VIDEO_FILES, AUDIO_FILES), HUMAN_ORDER); Map data = new TreeMap(); try (MediaInfo mi = new MediaInfo()) { diff --git a/source/net/filebot/ui/filter/SplitTool.java b/source/net/filebot/ui/filter/SplitTool.java index a10e2652..a257264a 100644 --- a/source/net/filebot/ui/filter/SplitTool.java +++ b/source/net/filebot/ui/filter/SplitTool.java @@ -76,8 +76,7 @@ class SplitTool extends Tool { int nextPart = 1; long splitSize = getSplitSize(); - List files = listFiles(root); - files.sort(HUMAN_ORDER); + List files = listFiles(root, FILES, HUMAN_ORDER); List rootGroup = new ArrayList(); List currentPart = new ArrayList(); diff --git a/source/net/filebot/ui/filter/Tool.java b/source/net/filebot/ui/filter/Tool.java index 29504676..2a5882ad 100644 --- a/source/net/filebot/ui/filter/Tool.java +++ b/source/net/filebot/ui/filter/Tool.java @@ -101,7 +101,7 @@ abstract class Tool extends JComponent { long totalSize = 0; for (File f : files) { - totalCount += FileUtilities.listFiles(f).size(); + totalCount += FileUtilities.listFiles(f, FileUtilities.FILES).size(); totalSize += FileUtils.sizeOf(f); } diff --git a/source/net/filebot/ui/filter/TypeTool.java b/source/net/filebot/ui/filter/TypeTool.java index ec554e39..76c761f2 100644 --- a/source/net/filebot/ui/filter/TypeTool.java +++ b/source/net/filebot/ui/filter/TypeTool.java @@ -45,7 +45,11 @@ class TypeTool extends Tool { @Override protected TreeModel createModelInBackground(File root) throws InterruptedException { - List filesAndFolders = (root != null) ? listFiles(singleton(root), FILE_WALK_MAX_DEPTH, true, true, true) : new ArrayList(); + if (root == null) { + return new DefaultTreeModel(new FolderNode("Types", emptyList())); + } + + List filesAndFolders = listFiles(root, f -> true, HUMAN_ORDER); List groups = new ArrayList(); for (Entry it : getMetaTypes().entrySet()) { diff --git a/source/net/filebot/ui/list/FileListTransferablePolicy.java b/source/net/filebot/ui/list/FileListTransferablePolicy.java index b241e1c1..9706561e 100644 --- a/source/net/filebot/ui/list/FileListTransferablePolicy.java +++ b/source/net/filebot/ui/list/FileListTransferablePolicy.java @@ -82,12 +82,9 @@ class FileListTransferablePolicy extends FileTransferablePolicy { title.accept(getFolderName(files.get(0))); } - List list = listFiles(files); - list.sort(HUMAN_ORDER); - // load all files from the given folders recursively up do a depth of 32 format.accept(ListPanel.DEFAULT_FILE_FORMAT); - model.accept(list); + model.accept(listFiles(files, FILES, HUMAN_ORDER)); } } diff --git a/source/net/filebot/ui/rename/NamesListTransferablePolicy.java b/source/net/filebot/ui/rename/NamesListTransferablePolicy.java index 40f4b3b5..4998b3fe 100644 --- a/source/net/filebot/ui/rename/NamesListTransferablePolicy.java +++ b/source/net/filebot/ui/rename/NamesListTransferablePolicy.java @@ -97,7 +97,7 @@ class NamesListTransferablePolicy extends FileTransferablePolicy { loadTorrentFiles(files, values); } else { // load all files from the given folders recursively up do a depth of 32 - listFiles(files).stream().sorted(HUMAN_ORDER).map(FastFile::new).forEach(values::add); + listFiles(files, FILES, HUMAN_ORDER).stream().map(FastFile::new).forEach(values::add); } model.addAll(values); diff --git a/source/net/filebot/ui/rename/Preset.java b/source/net/filebot/ui/rename/Preset.java index fde9834f..4d14a4de 100644 --- a/source/net/filebot/ui/rename/Preset.java +++ b/source/net/filebot/ui/rename/Preset.java @@ -84,13 +84,7 @@ public class Preset { } } - List files = listFiles(getInputFolder()); - if (filter != null) { - files = filter(files, filter); - } - files.sort(HUMAN_ORDER); - - return files; + return listFiles(getInputFolder(), f -> f.isFile() && filter.accept(f), HUMAN_ORDER); } public AutoCompleteMatcher getAutoCompleteMatcher() { diff --git a/source/net/filebot/ui/subtitle/SubtitleDropTarget.java b/source/net/filebot/ui/subtitle/SubtitleDropTarget.java index e9287333..3702b7fa 100644 --- a/source/net/filebot/ui/subtitle/SubtitleDropTarget.java +++ b/source/net/filebot/ui/subtitle/SubtitleDropTarget.java @@ -19,13 +19,11 @@ import java.awt.dnd.DropTargetEvent; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; -import java.util.ArrayList; import java.util.Collection; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Optional; -import java.util.TreeSet; import java.util.function.Function; import java.util.logging.Level; @@ -162,7 +160,7 @@ abstract class SubtitleDropTarget extends JButton { @Override protected DropAction getDropAction(List selection) { // accept video files and folders - return filter(input, VIDEO_FILES, FOLDERS).size() > 0 ? DropAction.Accept : DropAction.Cancel; + return filter(selection, VIDEO_FILES, FOLDERS).size() > 0 ? DropAction.Accept : DropAction.Cancel; } @Override @@ -177,8 +175,7 @@ abstract class SubtitleDropTarget extends JButton { return false; } - List files = filter(listFiles(selection), VIDEO_FILES); - files.sort(HUMAN_ORDER); + List files = listFiles(selection, VIDEO_FILES, HUMAN_ORDER); if (files.size() > 0) { handleDownload(files); @@ -252,13 +249,10 @@ abstract class SubtitleDropTarget extends JButton { } // perform a drop action depending on the given files - List files = listFiles(selection); + List files = listFiles(selection, FILES, HUMAN_ORDER); List videos = filter(files, VIDEO_FILES); - videos.sort(HUMAN_ORDER); - List subtitles = filter(files, SUBTITLE_FILES); - subtitles.sort(HUMAN_ORDER); Map uploadPlan = new LinkedHashMap(); diff --git a/source/net/filebot/util/FileUtilities.java b/source/net/filebot/util/FileUtilities.java index 3ba8c424..8d890d9a 100644 --- a/source/net/filebot/util/FileUtilities.java +++ b/source/net/filebot/util/FileUtilities.java @@ -390,6 +390,10 @@ public final class FileUtilities { return f -> !filter.accept(f); } + public static FileFilter filter(FileFilter... filters) { + return f -> stream(filters).anyMatch(it -> it.accept(f)); + } + public static List listPath(File file) { return listPathTail(file, Integer.MAX_VALUE, false); } @@ -455,54 +459,50 @@ public final class FileUtilities { public static final int FILE_WALK_MAX_DEPTH = 32; - public static List listFiles(File... folders) { - return listFiles(asList(folders)); + public static List listFiles(File folder, FileFilter filter) { + return listFiles(singleton(folder), FILE_WALK_MAX_DEPTH, filter, null); } - public static List listFiles(Iterable folders) { - return listFiles(folders, FILE_WALK_MAX_DEPTH, false, true, false); + public static List listFiles(File folder, FileFilter filter, Comparator order) { + return listFiles(singleton(folder), FILE_WALK_MAX_DEPTH, filter, order); } - public static List listFolders(Iterable folders) { - return listFiles(folders, FILE_WALK_MAX_DEPTH, false, false, true); + public static List listFiles(Iterable folders, FileFilter filter, Comparator order) { + return listFiles(folders, FILE_WALK_MAX_DEPTH, filter, order); } - public static List listFiles(Iterable folders, int maxDepth, boolean addHidden, boolean addFiles, boolean addFolders) { - List files = new ArrayList(); + public static List listFolders(Iterable folders, Comparator order) { + return listFiles(folders, FILE_WALK_MAX_DEPTH, FOLDERS, order); + } + + public static List listFiles(Iterable folders, int maxDepth, FileFilter filter, Comparator order) { + List sink = new ArrayList(); - // collect files from directory tree for (File it : folders) { - if (!addHidden && it.isHidden()) // ignore hidden files - continue; - if (it.isDirectory()) { - if (addFolders) { - files.add(it); - } - listFiles(it, files, 0, maxDepth, addHidden, addFiles, addFolders); - } else if (addFiles && it.isFile()) { - files.add(it); + listFiles(it, sink, 0, maxDepth, filter, order); + } + + if (filter.accept(it)) { + sink.add(it); } } - return files; + return sink; } - private static void listFiles(File folder, List files, int depth, int maxDepth, boolean addHidden, boolean addFiles, boolean addFolders) { - if (depth > maxDepth) + private static void listFiles(File folder, List sink, int depth, int maxDepth, FileFilter filter, Comparator order) { + if (depth > maxDepth) { return; + } - for (File it : getChildren(folder)) { - if (!addHidden && it.isHidden()) // ignore hidden files - continue; - + for (File it : getChildren(folder, NOT_HIDDEN, order)) { if (it.isDirectory()) { - if (addFolders) { - files.add(it); - } - listFiles(it, files, depth + 1, maxDepth, addHidden, addFiles, addFolders); - } else if (addFiles) { - files.add(it); + listFiles(it, sink, depth + 1, maxDepth, filter, order); + } + + if (filter.accept(it)) { + sink.add(it); } } }