Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to zip a directory's contents except one subdirectory?

Tags:

c#

zipfile

I'm attempting to create a zip file to serve as a backup of a directory, and eventually save that backup inside a "backups" folder in that directory. For illustration, "folder" includes "subFolder", "file1.txt", "file2.txt", and "backups". The "backups" folder would contain various earlier backup files. I want to create an archive of "folder" and all its contents, including subfolder, but exclude "backups".

Here is what I originally wanted to use:

ZipFile.CreateFromDirectory(folderToZip, backupFileName);

I realize there are problems with saving a zip file inside the folder being zipped, so I intended to save it somewhere else and then transfer it. But I don't know how to easily create an archive without the backups folder. My only thought is to write my own method recursively traversing the directory and excluding that one folder. It seems like there must be a simpler way.

Any help would be greatly appreciated!

like image 564
randomraccoon Avatar asked Feb 15 '16 17:02

randomraccoon


People also ask

Can you zip a folder that has subfolders?

Creating a zip folder allows files to be organized and compressed to a smaller file size for distribution or saving space. Zip folder can have subfolders within this main folder.

How do you zip all the .TXT files in a directory assume the directory doesn't contain any folders?

Syntax : $zip –m filename.zip file.txt 4. -r Option: To zip a directory recursively, use the -r option with the zip command and it will recursively zips the files in a directory. This option helps you to zip all the files present in the specified directory.

How do I compress multiple folders into a zip file?

To place multiple files into a zip folder, select all of the files while hitting the Ctrl button. Then, right-click on one of the files, move your cursor over the “Send to” option and select “Compressed (zipped) folder”.

How do I zip the contents of a directory?

To zip (compress) a file or folder Locate the file or folder that you want to zip. Press and hold (or right-click) the file or folder, select (or point to) Send to, and then select Compressed (zipped) folder. A new zipped folder with the same name is created in the same location.


2 Answers

Unfortunately, ZipFile does not offer a method that lets you filter entries. Fortunately, you can easily create a method like this based on this implementation:

public static class ZipHelper {
    public static void CreateFromDirectory(
        string sourceDirectoryName
    ,   string destinationArchiveFileName
    ,   CompressionLevel compressionLevel
    ,   bool includeBaseDirectory
    ,   Encoding entryNameEncoding
    ,   Predicate<string> filter // Add this parameter
    ) {
        if (string.IsNullOrEmpty(sourceDirectoryName)) {
            throw new ArgumentNullException("sourceDirectoryName");
        }
        if (string.IsNullOrEmpty(destinationArchiveFileName)) {
            throw new ArgumentNullException("destinationArchiveFileName");
        }
        var filesToAdd = Directory.GetFiles(sourceDirectoryName, "*", SearchOption.AllDirectories);
        var entryNames = GetEntryNames(filesToAdd, sourceDirectoryName, includeBaseDirectory);
        using(var zipFileStream = new FileStream(destinationArchiveFileName, FileMode.Create)) {
            using (var archive = new ZipArchive(zipFileStream, ZipArchiveMode.Create)) {
                for (int i = 0; i < filesToAdd.Length; i++) {
                    // Add the following condition to do filtering:
                    if (!filter(filesToAdd[i])) {
                        continue;
                    }
                    archive.CreateEntryFromFile(filesToAdd[i], entryNames[i], compressionLevel);
                }
            }
        }
    }
}

This implementation lets you pass a filter that rejects all entries from the "backup/" directory:

ZipHelper.CreateFromDirectory(
    myDir, destFile, CompressionLevel.Fastest, true, Encoding.UTF8,
    fileName => !fileName.Contains(@"\backup\")
);
like image 193
Sergey Kalinichenko Avatar answered Oct 01 '22 00:10

Sergey Kalinichenko


In my opinion, you can take every file inside the folder excluding the "backups" folder and make an temporary folder with them to make the zip as you have said.

With this LINQ query you can do it in a really simple way:

List<FileInfo> files = di.GetFiles("*", SearchOption.AllDirectories).Where(file => !file.DirectoryName.Contains("backups")).ToList();

Once you have this list, you can copy all this files, make the zip and erase the content. I can not see a simpler way.

like image 26
Ignacio Avatar answered Sep 30 '22 22:09

Ignacio