![搭建舞台](https://linux22.com/image/128718/%E6%90%AD%E5%BB%BA%E8%88%9E%E5%8F%B0.png)
如何在 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
只是作为另一个存档而被忽略,尽管这是一个无法打开的存档。
解释
我只能说自动检测。
文档
还没有
其他注意事项
我不确定这里使用diff
和cmp
检查相同性之间的区别。我一直在使用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 存档。