diff --git a/ParTool/Options/Extract.cs b/ParTool/Options/Extract.cs index 6c05e64..de46d7e 100644 --- a/ParTool/Options/Extract.cs +++ b/ParTool/Options/Extract.cs @@ -1,5 +1,5 @@ // ------------------------------------------------------- -// © Kaplas. Licensed under MIT. See LICENSE for details. +// © Kaplas, Samuel W. Stark (TheTurboTurnip). Licensed under MIT. See LICENSE for details. // ------------------------------------------------------- namespace ParTool.Options { @@ -29,5 +29,11 @@ internal class Extract /// [Option('r', "recursive", Default = false, HelpText = "Extract nested PAR archives.")] public bool Recursive { get; set; } + + /// + /// Gets or sets a value used as a Regex filter for which files to extract. + /// + [Option("filter", Default = null, HelpText = "Only extract files that match this RegEx (directories will always be extracted)")] + public string FilterRegex { get; set; } } } diff --git a/ParTool/Options/List.cs b/ParTool/Options/List.cs index 19528f9..81233f7 100644 --- a/ParTool/Options/List.cs +++ b/ParTool/Options/List.cs @@ -1,5 +1,5 @@ // ------------------------------------------------------- -// © Kaplas. Licensed under MIT. See LICENSE for details. +// © Kaplas, Samuel W. Stark (TheTurboTurnip). Licensed under MIT. See LICENSE for details. // ------------------------------------------------------- namespace ParTool.Options { @@ -23,5 +23,11 @@ internal class List /// [Option('r', "recursive", Default = false, HelpText = "List nested PAR archives.")] public bool Recursive { get; set; } + + /// + /// Gets or sets a value used as a Regex filter for which files to list. + /// + [Option("filter", Default = null, HelpText = "Only list files that match this RegEx")] + public string FilterRegex { get; set; } } } diff --git a/ParTool/Program.Extract.cs b/ParTool/Program.Extract.cs index 561a538..892ffdc 100644 --- a/ParTool/Program.Extract.cs +++ b/ParTool/Program.Extract.cs @@ -1,10 +1,11 @@ // ------------------------------------------------------- -// © Kaplas. Licensed under MIT. See LICENSE for details. +// © Kaplas, Samuel W. Stark (TheTurboTurnip). Licensed under MIT. See LICENSE for details. // ------------------------------------------------------- namespace ParTool { using System; using System.IO; + using System.Text.RegularExpressions; using ParLibrary; using ParLibrary.Converter; using Yarhl.FileSystem; @@ -39,6 +40,9 @@ private static void Extract(Options.Extract opts) Directory.CreateDirectory(opts.OutputDirectory); + // If a FilterRegex was specified (i.e. is not null) then make a new Regex using it. Otherwise, set filterRegex to null. + var filterRegex = (opts.FilterRegex == null) ? null : new Regex(opts.FilterRegex); + var parameters = new ParArchiveReaderParameters { Recursive = opts.Recursive, @@ -47,10 +51,10 @@ private static void Extract(Options.Extract opts) using Node par = NodeFactory.FromFile(opts.ParArchivePath, Yarhl.IO.FileOpenMode.Read); par.TransformWith(parameters); - Extract(par, opts.OutputDirectory); + Extract(par, filterRegex, opts.OutputDirectory); } - private static void Extract(Node parNode, string outputFolder) + private static void Extract(Node parNode, Regex filterRegex, string outputFolder) { foreach (Node node in Navigator.IterateNodes(parNode)) { @@ -65,6 +69,13 @@ private static void Extract(Node parNode, string outputFolder) continue; } + // If the filterRegex exists, skip files that don't match it + if (filterRegex != null && !filterRegex.IsMatch(node.Path)) + { + Console.WriteLine($"Skipping {node.Path}"); + continue; + } + Console.Write($"Extracting {node.Path}... "); if (file.IsCompressed) diff --git a/ParTool/Program.List.cs b/ParTool/Program.List.cs index 551df0a..68a2597 100644 --- a/ParTool/Program.List.cs +++ b/ParTool/Program.List.cs @@ -1,10 +1,11 @@ // ------------------------------------------------------- -// © Kaplas. Licensed under MIT. See LICENSE for details. +// © Kaplas, Samuel W. Stark (TheTurboTurnip). Licensed under MIT. See LICENSE for details. // ------------------------------------------------------- namespace ParTool { using System; using System.IO; + using System.Text.RegularExpressions; using ParLibrary; using ParLibrary.Converter; using Yarhl.FileSystem; @@ -24,6 +25,9 @@ private static void List(Options.List opts) return; } + // If a FilterRegex was specified (i.e. is not null) then make a new Regex using it. Otherwise, set filterRegex to null. + var filterRegex = (opts.FilterRegex == null) ? null : new Regex(opts.FilterRegex); + var parameters = new ParArchiveReaderParameters { Recursive = opts.Recursive, @@ -37,6 +41,12 @@ private static void List(Options.List opts) var file = node.GetFormatAs(); if (file != null) { + // If the filterRegex exists, skip files that don't match it + if (filterRegex != null && !filterRegex.IsMatch(node.Path)) + { + continue; + } + var compression = file.IsCompressed ? "*" : string.Empty; Console.WriteLine($"{node.Path}{compression}\t{file.DecompressedSize} bytes\t{file.FileDate:G}"); } diff --git a/README.md b/README.md index 36e3591..638edc4 100644 --- a/README.md +++ b/README.md @@ -10,20 +10,39 @@ It supports ***SLLZ*** compression (Including ***SLLZ V2*** used in Yakuza Kiwam ## Usage - **List mode** - `ParTool.exe list [-r]` + `ParTool.exe list [-r] [--filter '']` Reads a PAR archive and shows it contents. `-r` parameter enables *recursive* mode and shows the contents of nested PAR archives. + + `--filter` parameter filters output lines using a user-provided regular expression. + + For example, `ParTool.exe list mesh.par -r --filter '\.gmd$'` will only list GMD files (files that end with the characters '.gmd'). + See [https://regexr.com/7q33s] for an explanation of this regular expression, and [the .NET Regular Expression Quick Reference](https://learn.microsoft.com/en-us/dotnet/standard/base-types/regular-expression-language-quick-reference) for a complete guide to the syntax. + If using Powershell, use single quotes `'` to surround the expression to avoid variable expansion [(see the Powershell docs)](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_quoting_rules?view=powershell-7.4#single-quoted-strings). + If using Command Prompt, use double quotes. + - **Extraction mode** - `ParTool.exe extract [-r]` + `ParTool.exe extract [-r] [--filter '']` Extracts the PAR archive contents to the specified directory. `-r` parameter enables *recursive* mode and extracts the contents of nested PAR archives. - + + `--filter` parameter filters extracted files using a user-provided regular expression. + Files that do not match the filter will not be extracted. + Directories are always extracted. + When combined with `-r`, files matching the filter inside nested PAR archives will be extracted. + + For example, `ParTool.exe extract mesh.par -r --filter '\.gmd$'` will only extract GMD files (files that end with the characters '.gmd'). + See [https://regexr.com/7q33s] for an explanation of this regular expression, and [the .NET Regular Expression Quick Reference](https://learn.microsoft.com/en-us/dotnet/standard/base-types/regular-expression-language-quick-reference) for a complete guide to the syntax. + + If using Powershell, use single quotes `'` to surround the expression to avoid variable expansion [(see the Powershell docs)](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_quoting_rules?view=powershell-7.4#single-quoted-strings). + If using Command Prompt, use double quotes. + - **Creation mode** `ParTool.exe create [-c compression_mode] [--alternative-mode]`