搭建舞台

搭建舞台

如何在 CentOS 终端中提取多部分 7z 文件(doc.7z.001、doc.7z.002....、doc.7z.060)?我尝试使用下面的命令将所有部分连接到一个文件中,

cat doc.7z* > ./docs.7z

并使用此命令提取文件,

7za x docs.7z

这给了我这个错误,

    Scanning the drive for archives: 1 file, 32937135758 bytes (31 GiB)

Extracting archive: docs.7z ERROR: docs.7z docs.7z Open ERROR: Can not open the file as [7z] archive


ERRORS: Unexpected end of archive
     Can't open as archive: 1 Files: 0 Size:       0 Compressed: 0

答案1

搭建舞台

让我们首先创建一个输入文件。

$ dd if=/dev/random of=in bs=512 count=10
10+0 records in
10+0 records out
5120 bytes (5.1 kB, 5.0 KiB) copied, 0.00056488 s, 9.1 MB/s

目录中有什么?

$ ls -l
total 8
-rw-r----- 1 tomasz tomasz 5120 Jul 31 18:37 in

现在让我们构建一个多部分存档。

$ 7z a -v1k arch in

7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=en_GB.UTF-8,Utf16=on,HugeFiles=on,64 bits,2 CPUs Intel(R) Core(TM)2 Duo CPU     U9400  @ 1.40GHz (1067A),ASM)

Scanning the drive:
1 file, 5120 bytes (5 KiB)

Creating archive: arch.7z

Items to compress: 1

    
Files read from disk: 1
Archive size: 5238 bytes (6 KiB)
Everything is Ok

结果?

$ ls
arch.7z.001  arch.7z.002  arch.7z.003  arch.7z.004  arch.7z.005  arch.7z.006  in

现在让我们将旧的输入文件移开。

$ mv in in.o && ls
arch.7z.001  arch.7z.002  arch.7z.003  arch.7z.004  arch.7z.005  arch.7z.006  in.o

解决方案1

现在是时候将文件解压回来了。

$ 7z e -ai'!arch.*' -an

7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=en_GB.UTF-8,Utf16=on,HugeFiles=on,64 bits,2 CPUs Intel(R) Core(TM)2 Duo CPU     U9400  @ 1.40GHz (1067A),ASM)

Scanning the drive for archives:
6 files, 5238 bytes (6 KiB)
    
Extracting archive: arch.7z.001
--
Path = arch.7z.001
Type = Split
Physical Size = 1024
Volumes = 6
Total Physical Size = 5238
----
Path = arch.7z
Size = 5238
--
Path = arch.7z
Type = 7z
Physical Size = 5238
Headers Size = 114
Method = LZMA2:6k
Solid = -
Blocks = 1

Everything is Ok
      
Size:       5120
Compressed: 5238

看看我们现在有什么。

$ ls
arch.7z.001  arch.7z.002  arch.7z.003  arch.7z.004  arch.7z.005  arch.7z.006  in  in.o

所以in文件又回来了。和 一样吗in.o

$ diff in in.o && echo same
same

没有输出diff就足够了。

解释

行动路线是这样的:

7z e -ai'!arch.*' -an

完整的命令由以下元素组成:

  • 7z是基本命令
  • e代表提取
  • -ai选择要包含的档案。这个选项似乎在 7z 的各个版本中都是规范的,或者可能是编译的标准,我不确定。不过网上可以查到,比如这里。它的语法是-ai[r[-|0]]{@listfile|!wildcard},我只会解释我正在使用的选项。其他的可以通过文档的帮助来弄清楚。我使用的是!wildcard,这似乎遵循常见的通配模式,但对于初始的!,它引入了这种选择。
  • -an在我的系统上是这样定义的,-an : disable archive_name field.在流行的在线文档中确实找不到这样的内容这个。同样,它要么是编译的,要么是版本特定的。它使逻辑更清晰,因为通用命令语法得到了放松。更多相关内容如下。

该命令如下所示:

7z <command> [<switches>... ] <archive_name> [<file_names>... ] [<@listfiles>... ]

[此表示法中的存档名称是强制性的,与标有和 的参数相反]。所做-an的就是取消这项义务。

7z不使用它时,结果是这样的:

$ 7z e -ai'!arch.*'

7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=en_GB.UTF-8,Utf16=on,HugeFiles=on,64 bits,2 CPUs Intel(R) Core(TM)2 Duo CPU     U9400  @ 1.40GHz (1067A),ASM)



Command Line Error:
Cannot find archive name

然而,它可以通过仅使用来协商任何name 作为强制参数。无论如何都会被过滤掉。

再次检查一下,目录中有什么:

$ ls
arch.7z.001  arch.7z.002  arch.7z.003  arch.7z.004  arch.7z.005  arch.7z.006  in.o

并且可以进行以下操作。

$ 7z e -ai'!arch.*' asdf

7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=en_GB.UTF-8,Utf16=on,HugeFiles=on,64 bits,2 CPUs Intel(R) Core(TM)2 Duo CPU     U9400  @ 1.40GHz (1067A),ASM)

Scanning the drive for archives:
6 files, 5238 bytes (6 KiB)
    
Extracting archive: arch.7z.001
--
Path = arch.7z.001
Type = Split
Physical Size = 1024
Volumes = 6
Total Physical Size = 5238
----
Path = arch.7z
Size = 5238
--
Path = arch.7z
Type = 7z
Physical Size = 5238
Headers Size = 114
Method = LZMA2:6k
Solid = -
Blocks = 1

Everything is Ok
      
Size:       5120
Compressed: 5238

目录的新状态:

$ ls
arch.7z.001  arch.7z.002  arch.7z.003  arch.7z.004  arch.7z.005  arch.7z.006  in  in.o

而且结果应该是正确的。

$ sha224sum in in.o
fde74a72c7f4079db4ca18d96629a4f316cd76324bda9742cb2d6c5c  in
fde74a72c7f4079db4ca18d96629a4f316cd76324bda9742cb2d6c5c  in.o

文档

-an开关记录在Debian 的 7zz 人,在我的 Debian Bullseye 衍生版 man of 7z 和官方源代码中v.22.01可下载这里

具体原因很难追查,为什么-an在某些情况下没有记录该选项。根据我的发现,即使它的人没有记录,它也可能值得尝试。其原因是 p7zip 的文档似乎存在差异,这在 CentOS 上也是意料之中的。 man的源码,可以看到这里,没有记录此开关。同时,在同一来源库的多个其他地方也提到了它。 (与今天相同的主分支。)

$ grep -rPI '\B-an\b'
CPP/7zip/UI/Console/Main.cpp:    "  -an : disable archive_name field\n"
CPP/7zip/UI/P7ZIP/wxP7ZIP.cpp:static LPCWSTR kArchiveNoNameSwitch = L" -an";
CPP/7zip/UI/Common/CompressCall.cpp:static const char *kArcIncludeSwitches = " -an -ai";
CPP/7zip/UI/Common/CompressCall.cpp:    params.AddAscii(" -an");
GUI/p7zipForFilemanager:    ${P7ZIP} t -an -ai@${list}
GUI/p7zipForFilemanager:    ${P7ZIP} x ${flag_ad} -an -ai@${list}
GUI/p7zipForFilemanager:    ${P7ZIP} x ${flag_ad} -o"*" -an -ai@${list}
DOC/MANUAL/cmdline/commands/list.htm:  <A href="../switches/ar_no.htm">-an (Disable parsing of archive_name)</A><BR>
DOC/MANUAL/cmdline/commands/test.htm:  <A href="../switches/ar_no.htm">-an (Disable parsing of archive_name)</A><BR>
DOC/MANUAL/cmdline/commands/extract.htm:  <A href="../switches/ar_no.htm">-an (Disable parsing of archive_name)</A><BR>
DOC/MANUAL/cmdline/commands/extract_full.htm:  <A href="../switches/ar_no.htm">-an (Disable parsing of archive_name)</A><BR>
DOC/MANUAL/cmdline/switches/index.htm:<TR> <TD><A href="ar_no.htm">-an</A></TD> <TD><A href="ar_no.htm">Disable parsing of archive_name</A></TD></TR>
DOC/MANUAL/cmdline/switches/ar_include.htm:7z t -an -air!*.7z
DOC/MANUAL/cmdline/switches/ar_include.htm:  <A href="ar_no.htm">-an (Disable parsing of archive_name)</A>
DOC/MANUAL/cmdline/switches/ar_exclude.htm:7z t -an -ai!*.7z -ax!a*.7z
DOC/MANUAL/cmdline/switches/ar_exclude.htm:  <A href="ar_no.htm">-an (Disable parsing of archive_name)</A>
DOC/MANUAL/cmdline/switches/bs.htm:7z a -si -so -bsp2 -txz -an < file.tar > file.tar.xz
DOC/MANUAL/cmdline/switches/ar_no.htm:  <TITLE>-an (Disable parsing of archive_name) switch</TITLE>
DOC/MANUAL/cmdline/switches/ar_no.htm:<H1>-an (Disable parsing of archive_name) switch</H1>
DOC/MANUAL/cmdline/switches/ar_no.htm:-an
DOC/MANUAL/cmdline/switches/ar_no.htm:7z t -an -ai!*.7z -ax!a*.7z

我不会进行更深入的调查。我的猜测是,手册页在某个时候被忽略了,或者可能合并失败。不过,有趣的是,在 Debian 中一切都很好。解决这个问题值得单独的赏金。获胜者是我,因为这是补丁

我还找不到任何官方或非官方的解释来说明如何在没有-an开关的情况下应对。

另一种解决方案

我正在进行更深入的调查,我必须承认语法很奇怪并且没有很好的记录。

这是另一个解决方案,我还没有官方解释。

$ 7z e .

7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=en_GB.UTF-8,Utf16=on,HugeFiles=on,64 bits,2 CPUs Intel(R) Core(TM)2 Duo CPU     U9400  @ 1.40GHz (1067A),ASM)

Scanning the drive for archives:
7 files, 10358 bytes (11 KiB)
    
Extracting archive: ./arch.7z.001
--
Path = ./arch.7z.001
Type = Split
Physical Size = 1024
Volumes = 6
Total Physical Size = 5238
----
Path = arch.7z
Size = 5238
--
Path = arch.7z
Type = 7z
Physical Size = 5238
Headers Size = 114
Method = LZMA2:6k
Solid = -
Blocks = 1

Everything is Ok

Extracting archive: ./in.o
ERROR: ./in.o
Can not open the file as archive

    
Archives: 2
OK archives: 1
Can't open as archive: 1
Size:       5120
Compressed: 5238

$ diff in in.o && echo same
same

请注意,该arch.*系列已被正确识别,但in.o只是作为另一个存档而被忽略,尽管这是一个无法打开的存档。

解释

我只能说自动检测。

文档

还没有

其他注意事项

我不确定这里使用diffcmp检查相同性之间的区别。我一直在使用diff,而且它也一直都是我所期望的那样。一个简单的测试它是否能够处理二进制文件,继续之前使用的文件:

$ echo x >> in
$ diff in in.o
Binary files in and in.o differ

答案2

尝试

7z -v100m

这会将存档分割成 100MB 的文件。

7z -v 选项支持 bkmg(字节、千字节、兆字节、千兆字节

来源参考:https://superuser.com/questions/258872/split-files-on-windows-company-with-linux-cat

答案3

只是

7za x doc.7z.001

没有串联。

如果它不起作用,则说明文件已损坏或重命名。

检查doc.7z.001的内容

hexdump -C -n 32 doc.7z.001

前两个字节必须包含 7z

file doc.7z.001

必须说的是 7zip 存档。

相关内容