More .NET components

Multiple files operations

Compressing and decompressing multiple files #

Use Add method to add multiple files into a ZIP archive. Use Extract or ExtractAll methods to extract multiple files.

Compressing multiple files:

CSharp

// add directory "C:\MyData" into the root of the ZIP archive
// (directory "/MyData" is created in the ZIP archive)
zip.Add(@"C:\MyData");

// add content of directory "C:\MyData" into the root of the ZIP archive
// (directory "/MyData" is not created in the ZIP archive)
zip.Add(@"C:\MyData\*");

// add directory "C:\MyData" into the "/data" directory of the ZIP archive
// (directory "/data/MyData" is created in ZIP archive)
zip.Add(@"C:\MyData", "/data");

// add content of "C:\MyData" to "/data" directory of the ZIP archive
// (directory "/data/MyData" is not created in ZIP archive)
zip.Add(@"C:\MyData\*", "/data");

// add all files from "C:\MyData" directory only
// (files from subdirectories are not compressed)
zip.Add(@"C:\MyData\*", "/data", TraversalMode.MatchFilesShallow);

// add all ".txt" files from "C:\MyData" directory only
// (files from subdirectories are not compressed)
zip.Add(@"C:\MyData\*.txt", "/data", TraversalMode.MatchFilesShallow);

// add all ".txt" files under "C:\MyData" directory anywhere (recursively)
// (files from subdirectories are compressed as well)
zip.Add(@"C:\MyData\*.txt", "/data", TraversalMode.MatchFilesDeep);

The Add method can handle single files as well:

CSharp

// add a single local file into root of the ZIP archive
zip.Add(@"C:\MyData\file1.txt");

// add a single local file to the ZIP archive
// (target path has to be a directory)
// (if the target path doesn't exist, it will be created)
zip.Add(@"C:\MyData\file1.txt", "/data");

Decompressing multiple files:

CSharp

// extract whole ZIP archive to "C:\MyData\Out"
zip.ExtractAll(@"C:\MyData\Out");

// extract contents of zipped "/data" directory to "C:\MyData\Out"
zip.Extract("/data/*", @"C:\MyData\Out");

// extract all files from "/data" directory only
// (files from subdirectories are not decompressed)
zip.Extract("/data/*", @"C:\MyData\Out", TraversalMode.MatchFilesShallow);

// extract all "*.txt" files from "/data" directory only
// (files from subdirectories are not decompressed)
zip.Extract("/data/*.txt", @"C:\MyData\Out", TraversalMode.MatchFilesShallow);

// extract all "*.txt" files from "/data" directory anywhere recursively
// (files from subdirectories are decompressed as well)
zip.Extract("/data/*.txt", @"C:\MyData\Out", TraversalMode.MatchFilesDeep);

The Extract method can handle single files as well:

CSharp

// extract a single file from ZIP archive
// (target path has to be an existing local directory)
zip.Extract("/data/file1.txt", @"C:\MyData\Out");

Recursive directory compression and decompression #

Add and Extract methods make it possible to easily compress or decompress whole directories with all their content recursively.

Compressing files and directories recursively:

CSharp

// add content of a local directory to a ZIP archive
// (contents of "/data/Exports" go into "/data")
zip.Add(@"C:\MyData\Exports\*", "/data");

// add a whole local directory to a ZIP archive
// (contents of "/data/Exports" go into "/data/Exports")
zip.Add(@"C:\MyData\Exports", "/data");

Dempressing files and directories recursively:

CSharp

// extract contents of a ZIP archive directory
// (contents of "/data/Exports" go into "C:\MyData\Out")
zip.Extract("/data/Exports/*", @"C:\MyData\Out");

// extract whole ZIP archive directory
// (contents of "/data/Exports" go into "C:\MyData\Out\Exports")
zip.Extract("/data/Exports", @"C:\MyData\Out");

Deleting multiple files #

To delete multiple files, use Delete method:

CSharp

// delete all files from "/data" ZIP archive directory only
// (keeps files in subdirectories)
zip.Delete("/data/*", TraversalMode.MatchFilesShallow);

// delete all ".txt" files from "/data" ZIP archive directory only
// (keeps ".txt" files in subdirectories)
zip.Delete("/data/*.txt", TraversalMode.MatchFilesShallow);

// delete all ".html" files anywhere in "/data" directory
// (deletes ".html" files in subdirectories as well)
zip.Delete("/data/*.html", TraversalMode.MatchFilesDeep);

Deleting directories recursively #

Delete method makes it possible to delete whole directories recursively as well:

CSharp

// only delete the contents of a ZIP archive directory
// (keep the "/data" directory itself)
zip.Delete("/data/*", TraversalMode.Recursive);

// delete a ZIP archive directory with all its contents recursively
zip.Delete("/data", TraversalMode.Recursive);

Using wildcards #

Wildcards make it possible to easily specify multiple files or directories whose names match a pattern. Supported wildcards are:

  • asterisk - * - matches any number (0, 1 or more) of any characters except a directory separator ("a*b" matches "ab", "axb", "axyzb", but not "a/b" or "ax/yb")
  • question mark - ? - matches exactly one character except a directory separator ("a?b" matches "axb" and "ayb", but not "ab", "axyzb" or "a/b")

CSharp

// add all January ".csv" exports from 2000
// (files go directly into the root of the ZIP archive)
zip.Add(@"C:\MyData\Exports\2000-01-??.csv");

// add all ".txt" files from "C:\MyData" with shallow matching
// (no files from subdirectories are added)
zip.Add(@"C:\MyData\*.txt", "/data", TraversalMode.MatchFilesShallow);

// add all ".txt" files from "C:\MyData" with deep matching
// (files from subdirectories are added as well)
zip.Add(@"C:\MyData\*.txt", "/data", TraversalMode.MatchFilesDeep);
Tip: Wildcard pattern matching mode can be tuned using the optional TraversalMode argument. For more information, see Advanced Download and Upload blog post.

Using file sets #

When simple wildcard patterns are not powerful enough, use Rebex.IO.FileSet class. It makes it possible to combine multiple matching criteria (such as all ".txt" and ".csv" files) and to specify exclusion criteria as well.

In addition to common wildcards and traversal modes, a special "**" wildcard is available that matches any character, including directory separators ("/MyData/**/file.txt" matches "/MyData/file.txt" and also "/MyData/a/b/c/file.txt").

CSharp

// create a file set
var fileSet = new Rebex.IO.FileSet(@"C:\MyData");
// include some files - paths/masks are relative to "C:\MyData" base path
fileSet.Include("*.txt", TraversalMode.MatchFilesShallow);
// include some directories
fileSet.Include("*Web*");
// exclude all ".tmp" files (in any location)
fileSet.Exclude("*.tmp", TraversalMode.MatchFilesDeep);
// exclude "Backups" directories (in any location)
fileSet.Exclude("**/Backups");
// exclude "C:\MyData\Ignore" directory
fileSet.Exclude("Ignore");

// display all the files to be compressed
Console.WriteLine("Archiving files:");
foreach (LocalItem item in fileSet.GetLocalItems())
{
    Console.WriteLine(item.FullPath);
}

// compress all files and directories matching the file set
zip.Add(fileSet);

If wildcard patterns are still not powerful enough, you can extend the FileSet class and add custom matching code. Just inherit from Rebex.IO.FileSet and override the IsMatch method. Check out our Advanced file filtering forum post for sample code.

Merging multiple directories #

File sets can optionally flatten a directory hierarchy, making it possible to compress/decompress files from multiple directories into a single one. Just set Rebex.IO.FileSet.Flatten to true before calling Add or Extract methods to achieve this.

For example, when adding files "A\a.txt" and "B\b.txt" to "/MyData" directory, both files will end up in the "/MyData" directory ("A" and "B" directories are not created).

CSharp

// prepare a file set
// (all files from "C:\MyData" and its subdirectories)
var fileSet = new Rebex.IO.FileSet(@"C:\MyData", "*.html");
fileSet.Flatten = true;

// add the files
zip.Add(fileSet);

Move mode #

Add and Extract methods support move mode, where files and directories are deleted once successfully processed - just specify TransferMethod.Move mode in the method call.

To further refine the moving behavior, set ZipArchive.Options.MultiFileMoveMode to:

  • MoveMode.All (default) - move both files and directories
  • MoveMode.FilesOnly - move files only (keep source directory structure)

CSharp

// this is the default mode (it's not necessary to set it)
zip.Options.MultiFileMoveMode = MoveMode.All;
// compress the whole directory "Exports" into the ZIP archive in move mode
// (directory "C:\MyData\Exports" will be deleted)
zip.Add(@"C:\MyData\Exports", "/data", 0, TransferMethod.Move, 0);

// specify that only files are to be moved
zip.Options.MultiFileMoveMode = MoveMode.FilesOnly;
// compress contents of "C:\MyData" directory into the ZIP archive in move mode
// (deletes successfully added files but keeps source directory structure)
zip.Add(@"C:\MyData\*", "/data", 0, TransferMethod.Move, 0);

Symlink detection and handling #

Add and Extract methods automatically detect symbolic links. To specify whether to resolve them, skip them or raise an error, set Options.MultiFileLinkMode to:

  • FollowLinks - resolve links and process them like other items
  • SkipLinks - skip links and continue processing
  • ThrowExceptionOnLinks - cancel processing by throwing an exception

CSharp

// do not process links
zip.Options.MultiFileLinkMode = LinkProcessingMode.SkipLinks;

// add directory without links
zip.Add(@"C:\MyData\*", "/data/NoLinks");

Note: Multi-file methods contain built-in infinite loop detection. When an infinite loop in the directory structure is detected, a ProblemDetected event is raised with ProblemDetectedEventArgs.ProblemType set to InfiniteLoopDetected.

Note: Extraction of symlinks is not supported. You have to process symlinks manually. See Resolving symlinks to learn, how to process symlinks.