diff --git a/source/net/sourceforge/filebot/archive/Archive.java b/source/net/sourceforge/filebot/archive/Archive.java index a69ba092..b8f4f97a 100644 --- a/source/net/sourceforge/filebot/archive/Archive.java +++ b/source/net/sourceforge/filebot/archive/Archive.java @@ -95,6 +95,27 @@ public class Archive implements Closeable { } + public void extract(ExtractOutProvider outputMapper, FileFilter filter) throws SevenZipException { + List selection = new ArrayList(); + + for (int i = 0; i < inArchive.getNumberOfItems(); i++) { + boolean isFolder = (Boolean) inArchive.getProperty(i, PropID.IS_FOLDER); + if (!isFolder) { + String path = (String) inArchive.getProperty(i, PropID.PATH); + if (path != null && filter.accept(new File(path))) { + selection.add(i); + } + } + } + + int[] indices = new int[selection.size()]; + for (int i = 0; i < indices.length; i++) { + indices[i] = selection.get(i); + } + inArchive.extract(indices, false, new ExtractCallback(inArchive, outputMapper)); + } + + @Override public void close() throws IOException { try { @@ -121,7 +142,6 @@ public class Archive implements Closeable { return extensions; } - public static final FileFilter VOLUME_ONE_FILTER = new FileFilter() { private Pattern volume = Pattern.compile("[.]r[0-9]+$|[.]part[0-9]+|[.][0-9]+$", Pattern.CASE_INSENSITIVE); diff --git a/source/net/sourceforge/filebot/cli/ArgumentProcessor.java b/source/net/sourceforge/filebot/cli/ArgumentProcessor.java index e4f9af8e..2b5af288 100644 --- a/source/net/sourceforge/filebot/cli/ArgumentProcessor.java +++ b/source/net/sourceforge/filebot/cli/ArgumentProcessor.java @@ -79,7 +79,7 @@ public class ArgumentProcessor { Collection files = new LinkedHashSet(args.getFiles(true)); if (args.extract) { - files.addAll(cli.extract(files, args.output, args.conflict)); + files.addAll(cli.extract(files, args.output, args.conflict, null, true)); } if (args.getSubtitles) { diff --git a/source/net/sourceforge/filebot/cli/CmdlineInterface.java b/source/net/sourceforge/filebot/cli/CmdlineInterface.java index 59986f3e..5cae2efe 100644 --- a/source/net/sourceforge/filebot/cli/CmdlineInterface.java +++ b/source/net/sourceforge/filebot/cli/CmdlineInterface.java @@ -3,6 +3,7 @@ package net.sourceforge.filebot.cli; import java.io.File; +import java.io.FileFilter; import java.util.Collection; import java.util.List; @@ -32,6 +33,6 @@ public interface CmdlineInterface { String getMediaInfo(File file, String format) throws Exception; - List extract(Collection files, String output, String conflict) throws Exception; + List extract(Collection files, String output, String conflict, FileFilter filter, boolean forceExtractAll) throws Exception; } diff --git a/source/net/sourceforge/filebot/cli/CmdlineOperations.java b/source/net/sourceforge/filebot/cli/CmdlineOperations.java index b572e643..6e7d7cbd 100644 --- a/source/net/sourceforge/filebot/cli/CmdlineOperations.java +++ b/source/net/sourceforge/filebot/cli/CmdlineOperations.java @@ -980,7 +980,7 @@ public class CmdlineOperations implements CmdlineInterface { @Override - public List extract(Collection files, String output, String conflict) throws Exception { + public List extract(Collection files, String output, String conflict, FileFilter filter, boolean forceExtractAll) throws Exception { ConflictAction conflictAction = ConflictAction.forName(conflict); // only keep single-volume archives or first part of multi-volume archives @@ -995,22 +995,51 @@ public class CmdlineOperations implements CmdlineInterface { outputFolder = new File(file.getParentFile(), outputFolder.getPath()); } - CLILogger.info(String.format("Extract archive [%s] to [%s]", file.getName(), outputFolder)); + CLILogger.info(String.format("Read archive [%s] to [%s]", file.getName(), outputFolder)); FileMapper outputMapper = new FileMapper(outputFolder, false); - List entries = archive.listFiles(); + final List outputMapping = new ArrayList(); + for (File entry : archive.listFiles()) { + outputMapping.add(outputMapper.getOutputFile(entry)); + } + + final Set selection = new TreeSet(); + for (File future : outputMapping) { + if (filter == null || filter.accept(future)) { + selection.add(future); + } + } + + // check if there is anything to extract at all + if (selection.isEmpty()) { + continue; + } + boolean skip = true; - for (File entry : entries) { - File outputFile = outputMapper.getOutputFile(entry); - skip &= outputFile.exists(); - extractedFiles.add(outputFile); + for (File future : filter == null || forceExtractAll ? outputMapping : selection) { + skip &= future.exists(); } if (!skip || conflictAction == ConflictAction.OVERRIDE) { - CLILogger.finest("Extracting files " + entries); - archive.extract(outputMapper); + if (filter == null || forceExtractAll) { + CLILogger.finest("Extracting files " + outputMapping); + // extract all files + archive.extract(outputMapper); + extractedFiles.addAll(outputMapping); + } else { + CLILogger.finest("Extracting files " + selection); + // extract files selected by the given filter + archive.extract(outputMapper, new FileFilter() { + + @Override + public boolean accept(File entry) { + return selection.contains(entry); + } + }); + extractedFiles.addAll(selection); + } } else { - CLILogger.finest("Skipped extracting files " + entries); + CLILogger.finest("Skipped extracting files " + selection); } } finally { archive.close(); @@ -1019,5 +1048,4 @@ public class CmdlineOperations implements CmdlineInterface { return extractedFiles; } - } diff --git a/source/net/sourceforge/filebot/cli/ScriptShell.lib.groovy b/source/net/sourceforge/filebot/cli/ScriptShell.lib.groovy index 673c0a98..930e725b 100644 --- a/source/net/sourceforge/filebot/cli/ScriptShell.lib.groovy +++ b/source/net/sourceforge/filebot/cli/ScriptShell.lib.groovy @@ -264,7 +264,7 @@ def compute(args) { args = _defaults(args) def extract(args) { args = _defaults(args) synchronized (_cli) { - _guarded { _cli.extract(_files(args), args.output as String, args.conflict as String) } + _guarded { _cli.extract(_files(args), args.output as String, args.conflict as String, args.filter instanceof Closure ? args.filter as FileFilter : null, args.forceExtractAll != null ? args.forceExtractAll : false) } } } @@ -319,17 +319,10 @@ def _renameFunction(fn) { * Fill in default values from cmdline arguments */ def _defaults(args) { - args.action = args.action ?: _args.action - args.conflict = args.conflict ?: _args.conflict - args.query = args.query ?: _args.query - args.filter = args.filter ?: _args.filter - args.format = args.format ?: _args.format - args.db = args.db ?: _args.db - args.order = args.order ?: _args.order - args.lang = args.lang ?: _args.lang - args.output = args.output ?: _args.output - args.encoding = args.encoding ?: _args.encoding - args.strict = args.strict != null ? args.strict : !_args.nonStrict + ['action', 'conflict', 'query', 'filter', 'format', 'db', 'order', 'lang', 'output', 'encoding'].each{ k -> + args[k] = args.containsKey(k) ? args[k] : _args[k] + } + args.strict = args.strict != null ? args.strict : !_args.nonStrict // invert strict/non-strict return args } diff --git a/website/scripts/utorrent-postprocess.groovy b/website/scripts/utorrent-postprocess.groovy index 9315c9b4..f713d720 100644 --- a/website/scripts/utorrent-postprocess.groovy +++ b/website/scripts/utorrent-postprocess.groovy @@ -47,11 +47,12 @@ if (args.empty) { input += args.getFiles() } -// extract archives if necessary -input += extract(file:input, output:".", conflict:"override") + +// extract archives (zip, rar, etc) that contain at least one video file +input += extract(file: input.findAll{ it.isArchive() }, output: null, conflict: 'override', filter: { it.isVideo() }, forceExtractAll: true) // process only media files -input = input.findAll{ it.isVideo() || it.isSubtitle() } +input = input.unique().findAll{ it.isVideo() || it.isSubtitle() } // ignore clutter files input = input.findAll{ !(it.path =~ /\b(?i:sample|trailer|extras|deleted.scenes|music.video|scrapbook)\b/) }