通过命令行创建 7-Zip 存档时创建逻辑文件夹结构

Creating a logical folder structure when creating a 7-Zip archive via the command-line

我一直在使用“DotNetZip”库使用如下代码归档文件:

var files = new []
{
    new { file = new FileInfo(@"C:\_test\Data\Testing\data.txt"), source = "Data" },
    new { file = new FileInfo(@"C:\_test\Logs\Testing\data.txt"), source = "Logs" },
};  

using (Ionic.Zip.ZipFile zipFile = new Ionic.Zip.ZipFile())
{
    zipFile.CompressionLevel = Ionic.Zlib.CompressionLevel.BestCompression;
    foreach (var f in files)
    {
        zipFile.AddFile(f.file.FullName, f.source);
    }
    zipFile.Save(@"C:\_test\output.zip");
}

这里要注意的关键是文件名是相同的,它们直接包含在同名文件夹中,当我创建 Zip 文件时,我正在为文件创建逻辑文件夹所以没有文件名冲突。

问题是 Zip 压缩太糟糕了。事实上,我有一些例子,说明我把一堆小文件放在哪里,然后得到一个更大的 Zip!

然后我使用 7-Zip 进行了测试,结果非常好。文件大小比 Zip 小得多。

所以,我尝试使用 7-Zip 重写我的代码,但似乎没有适合 .NET 的 7-Zip 库,唯一的选择是通过命令使用 7-Zip行。

我在 Powershell 中尝试过:

."C:\Program Files-Zipz.exe" a -mx9 "C:\_test210112 Testing.7z" "C:\_test\Data\Testing\data.txt" "C:\_test\Logs\Testing\data.txt"

但我得到了这个输出:

7-Zip 19.00 (x64) : Copyright (c) 1999-2018 Igor Pavlov : 2019-02-21

Scanning the drive:
2 files, 40 bytes (1 KiB)

Creating archive: C:\_test\__test.7z

ERROR:
Duplicate filename on disk:
data.txt
data.txt

如果我添加 -spf 命令行,它就可以工作,但我的存档现在是用从 C.

开始的每个文件夹创建的

在从命令行添加项目时,7-Zip 是否允许它创建逻辑文件夹结构?

明确地说,我正在选择要存档的文件夹中的一部分文件,我想将它们放在逻辑文件夹中。

如果您只是想压缩文件夹中的所有内容,那么您可以这样做,它会保持文件夹结构。

."C:\Program Files-Zipz.exe" a -mx9 "C:\_test210112 Testing.7z" "C:\_test\*"

编辑: 要有选择地归档某些文件,请使用相对路径。在您的情况下,您可以将 C:\_test 设置为当前目录,然后设置 运行

."C:\Program Files-Zipz.exe" a -mx9 "C:\_test210112 Testing.7z" "Data\Testing\data.txt" "Logs\Testing\data.txt"

有趣的问题。我经常使用 7z,但我从来不需要这样的工作流程。

如您所知,您收到错误是因为在存档中您有平面结构的重复文件。 7z 存档器不知道使用哪一个,因此出现错误。

我认为你很接近,但问题是你正在使用完全分类的路径来访问要打包的文件。

解决方案

您的解决方案是 运行 来自 C:\_test\7z:

"C:\Program Files-Zipz.exe" a -mx9 -spf2 "C:\_test210112_Testing.7z" "Data\Testing\data.txt" "Logs\Testing\data.txt"

现在您的存档将具有相同文件名的不同路径。我还建议 不要 在 7z 文件名中使用 space - 你将来会省去麻烦。如果您有基于输入的相对或绝对路径,-spf2 开关将进行调整。如果我需要混合它,我倾向于把它放在那里。

备注

我喜欢使用 -spf2(不包括完整路径中的驱动器号)开关,因为这样可以在 OS.

之间切换时更轻松

我们从代码中使用 SevenZipSharp NuGet 包。它有一个 CompressFileDictionary 功能,它可以添加字典中存在的所有文件,因此您可以挑选要添加的文件。

示例:

private void CreateArchive(string archivePath, Dictionary<string, string> materialsToArchive, int part)
{
    SevenZip.SevenZipCompressor.SetLibraryPath(Properties.Settings.Default.Location7zDll);
    SevenZip.SevenZipCompressor compressor = new SevenZip.SevenZipCompressor()
    {
        CompressionMode = part == 0 ? SevenZip.CompressionMode.Create : SevenZip.CompressionMode.Append,
        ArchiveFormat = SevenZip.OutArchiveFormat.Tar,
        CompressionMethod = SevenZip.CompressionMethod.Copy,
        CompressionLevel = SevenZip.CompressionLevel.None,
        IncludeEmptyDirectories = true,
        TempFolderPath = Path.GetDirectoryName(archivePath)
    };

    compressor.Compressing += new EventHandler<SevenZip.ProgressEventArgs>(CompressorCompressing);
    lastPercent = 0;
    firstTransfer = true;
    compressor.CompressFileDictionary(materialsToArchive, archivePath);
}

字典条目的键是 zip 中的相对路径,值是文件的真实路径...

Is there a way in 7-Zip to allow it to create a logical folder structure when adding items from the command line?

To be clear, I'm selecting a subset of the files in the folders to be archived and I want to place them in logical folders.

很遗憾,7-Zip 中没有这样的方式。作者在他的sourceforge site in 2015. Since then, there has not been any update上证实了这一点。

内置的 PowerShell cmdlet Compress-Archive 也不支持此功能。


您只能通过一个明显的解决方法来实现:临时创建逻辑文件夹结构,将文件复制到其中,存档此临时文件夹结构,然后将其删除。如果你想保留你的文件的时间戳 - 这将被常规复制操作改变 - 你可以使用 Robocopy.exe (已经内置在 Windows 中)与 /COPY:DAT /DCOPY:DAT执行复制操作的参数。