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

6

我一直在使用像这样的代码使用 "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\7-Zip\7z.exe" a -mx9 "C:\_test\20210112 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中,是否有一种方法可以允许从命令行添加项目时创建逻辑文件夹结构?
明确一下,我正在选择要归档的文件夹中的子集,并希望将它们放置在逻辑文件夹中。
4个回答

5
如果您只想将文件夹中的所有内容打包成zip文件,那么可以这样做,它将维护文件夹结构。
."C:\Program Files\7-Zip\7z.exe" a -mx9 "C:\_test\20210112 Testing.7z" "C:\_test\*"

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

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

对不起,我的问题没有表达清楚 - 我选择性地归档文件,而不是归档每个文件。通配符不能解决这个问题。我有一个特定的文件子集需要进行归档。 - Enigmativity

2
有趣的问题。我经常使用7z,但从未需要过这样的工作流程。
正如你所知,由于在归档文件中存在平面结构中的重复文件,所以会出现错误。7z存档程序不知道该使用哪一个,因此会出现错误。
我认为你很接近解决方法,但问题在于你正在使用完全分类的路径来访问文件进行打包。
解决方法是从C:\_test\运行7z:
"C:\Program Files\7-Zip\7z.exe" a -mx9 -spf2 "C:\_test\20210112_Testing.7z" "Data\Testing\data.txt" "Logs\Testing\data.txt"
现在你的归档文件将拥有相同文件名的不同路径。我还建议不要在7z文件名中使用空格-这将使你在未来避免麻烦。 -spf2开关将根据输入调整相对或绝对路径。如果需要混合使用,我倾向于将其放在那里。
注意:我喜欢使用-spf2(不包括完整路径中的驱动器号)开关,因为在操作系统之间切换时可以更方便。

2

在使用命令行添加项目时,有没有一种方法可以让7-Zip创建逻辑文件夹结构?

明确一点,我正在选择要存档的文件夹中的文件子集,并希望将它们放置在逻辑文件夹中。

很遗憾,在7-Zip中没有这样的方式。作者在2015年在他的sourceforge网站上确认了这一点。从那以后,也没有任何更新

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


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


这正是我最终所做的。我有一些文件,它们不在逻辑结构中,但想要将它们压缩到一个逻辑结构中。最终,创建一个临时文件夹,执行7z a,然后删除它似乎是最简单的解决方案。 - Dan Atkinson

1
我们在代码中使用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文件中的相对路径,值是文件的真实路径...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接