我使用的是7z版本18.05,我只想列出存档内容的文件名。
如果我使用命令7z l myArchive.7z
,则会得到以下输出:
7-Zip 18.05 (x64) : Copyright (c) 1999-2018 Igor Pavlov : 2018-04-30
Scanning the drive for archives:
1 file, 146863932 bytes (141 MiB)
Listing archive: myArchive.7z
--
Path = myArchive.7z
Type = 7z
Physical Size = 146863932
Headers Size = 393
Method = LZMA:26
Solid = +
Blocks = 1
Date Time Attr Size Compressed Name
------------------- ----- ------------ ------------ ------------------------
2017-12-06 08:55:47 D...A 0 0 myArchive
2017-12-06 08:55:42 D...A 0 0 myArchive\folder
2017-12-05 19:50:41 ....A 21816530 146863539 myArchive\folder\Test.dat
2017-12-06 08:55:42 ....A 21877463 myArchive\folder\Test2.dat
2017-12-05 19:51:05 ....A 153953 myArchive\folder\Test3.dat
2017-12-05 19:50:41 ....A 4193 myArchive\folder\Test4.dat
2017-12-06 08:55:47 ....A 24128956 myArchive\log.txt
2017-12-06 08:55:47 ....A 79980 myArchive\readme.txt
2017-12-05 19:51:05 ....A 3256759999 myArchive\folder\zTest.txt
------------------- ----- ------------ ------------ ------------------------
2017-12-06 08:55:47 3324821074 146863539 7 files, 2 folders
我不知道为什么7z没有列出仅文件名的开关。如何仅获取“名称”列?有建议使用dos命令吗?
答案 0 :(得分:2)
我正在寻找这个确切问题的答案,并在 Nisse Knudsen 提供的链接中找到了答案,但对我而言,-ba
未记录的开关本身无法完成我需要的功能,这个开关本身(也不是 Nisse 的答案)似乎也不能完全回答 OP 的问题 - OP 想知道如何只获取(每个文件的)名称,而 -ba
单独在解析数据时并不总是有效.7z
文件。我会发表评论而不是完整的答案,但我没有获得足够的代表来发表评论,我相信这些信息仍然相关且准确,无论如何我的“评论”都会太长。
使用 -slt
开关引用 Nisse (https://superuser.com/a/1073272/542975) 提供的链接以更易读的格式(用于循环/解析目的)格式化输出,其中一个简单的 For /f
循环一个批处理文件可以解析并为您提供所需的内容。
让我列出输出中的一些更改,以便您了解每个开关的作用。
这个:7z.exe l "C:\Some Directory\Some FileIZipped.zip"
7-Zip [64] 15.12 : Copyright (c) 1999-2015 Igor Pavlov : 2015-11-19
Scanning the drive for archives:
1 file, 9986888 bytes (10 MiB)
Listing archive: C:\Some Directory\Some FileIZipped.zip
--
Path = C:\Some Directory\Some FileIZipped.zip
Type = zip
Physical Size = 9986888
Date Time Attr Size Compressed Name
------------------- ----- ------------ ------------ ------------------------
2017-07-18 12:19:04 ....A 240789 109401 A_RandomFile.doc
2017-07-05 13:32:42 ....A 19148800 9877487 Another_Random File with Spaces.mov
------------------- ----- ------------ ------------ ------------------------
2017-07-18 16:30:44 19389589 9986888 2 files
变成这样:7z.exe l -slt "C:\Some Directory\Some FileIZipped.zip"
7-Zip [64] 15.12 : Copyright (c) 1999-2015 Igor Pavlov : 2015-11-19
Scanning the drive for archives:
1 file, 9986888 bytes (10 MiB)
Listing archive: C:\Some Directory\Some FileIZipped.zip
--
Path = C:\Some Directory\Some FileIZipped.zip
Type = zip
Physical Size = 9986888
----------
Path = A_RandomFile.doc
Folder = -
Size = 240789
Packed Size = 109401
----[10 lines of jargon removed for clarity]----
Path = Another_Random File with Spaces.mov
Folder = -
Size = 19148800
Packed Size = 9877487
----[10 lines of jargon removed for clarity]----
添加 -ba
命令进一步简化了格式,无需跳过标题行(我在 for 循环的注释中引用了这一点,如最后的脚本示例所示)。>
这进一步变成:7z.exe l -ba -slt "C:\Some Directory\Some FileIZipped.zip"
Path = A_RandomFile.doc
Folder = -
Size = 240789
Packed Size = 109401
----[10 lines of jargon removed for clarity]----
Path = Another_Random File with Spaces.mov
Folder = -
Size = 19148800
Packed Size = 9877487
----[10 lines of jargon removed for clarity]----
我将此用作将存档 (zip/7z/rar) 与实际目录进行文件比较的方法,以制作该目录为主的镜像副本。为此,我正在解析一个包含 7z list 命令输出的文件。我想我可以直接从 7z 命令迭代 for 循环,但我发现在某些情况下,当档案中有大量数据时,这会变慢。
我有多个尝试解析标准输出失败的实例 - 当列出 .7z
存档的内容时会发生这种情况,如下所示。这不是 - 轻松 - 使用 for 循环解析空格来解决的。对于大多数行(显示为压缩空间)而言,Token 5
最终会成为 .zip
格式存档中保留的文件名 Token 6
,因此您会遇到非常混乱的情况一场噩梦计划。这也是 OP 在提供的示例中引用的确切问题。
类似于 OP 提供的示例:
7-Zip [64] 15.12 : Copyright (c) 1999-2015 Igor Pavlov : 2015-11-19
Scanning the drive for archives:
1 file, 446600 bytes (437 KiB)
Listing archive: C:\Some Directory\Some _OTHER_ FileIZipped.7z
--
Path = C:\Some Directory\Some _OTHER_ FileIZipped.7z
Type = 7z
Physical Size = 446600
Headers Size = 283
Method = LZMA2:22
Solid = +
Blocks = 1
Date Time Attr Size Compressed Name
------------------- ----- ------------ ------------ ------------------------
2020-08-28 15:06:46 D.... 0 0 SomeDirectoryInside
2020-08-28 15:06:46 D.... 0 0 SomeDirectoryInside\OtherDir
2020-08-28 15:06:46 D.... 0 0 SomeDirectoryInside\Zips
2020-08-28 15:13:14 ..... 1064960 446317 SomeDirectoryInside\Zips\Some_File.Doc
2020-08-28 15:08:02 ..... 313080 SomeDirectoryInside\Zips\Some_Other_File.Doc
2020-08-28 15:07:34 ..... 1561728 SomeDirectoryInside\Zips\Foo.mov
2020-08-28 15:07:46 ..... 262144 SomeDirectoryInside\Zips\Fancy.Doc
2020-08-28 15:07:26 ..... 262144 SomeDirectoryInside\Zips\Fancy2.Doc
------------------- ----- ------------ ------------ ------------------------
2020-08-28 15:13:14 3464056 446317 5 files, 3 folders
下面是我编写的批处理脚本示例,用于将 7z.exe
输出放入文件中,然后从文件中提取数据并获取我需要的数据。原谅多个 REM 行 - 我更喜欢这种注释方法而不是长的单行字符串,这样读者就不必为了阅读而向右滚动代码块。
由于 For /f
如何遍历数据,我们需要确保令牌 %%c
不为空。我使用这种方法是因为有时我们的文件名称中有空格,我们使用空格作为分隔符来解析 7z
输出。
令牌 3*
会给你两个单独的令牌,你可以检查 - 令牌 %%b
[ 令牌 3 ] 和 %%c
[ 令牌 * ] - 如果 %%c
为空 -我们知道 %%b
没有空格,可以安全地回显到我们需要的任何文件或设置为稍后使用的变量等。
@Echo Off
REM Sending the output of 7z into a file to use later
7z.exe l -slt "SomeFileIZipped.zip" >"ZipListRAW.txt"
REM Example of 7z.exe command with '-ba' switch
REM 7z.exe l -ba -slt "SomeFileIZipped.zip"
REM If you do not use '-ba' in the 7z command above, you can simply skip the first
REM 11-12 lines of the file to get ONLY the filenames (skips past first line containing
REM "Path" which contains the original archive filename.
For /f "Usebackq Skip=11 Tokens=1,3* Delims= " %%a in ("ZipListRAW.txt") do (
REM Checking if %%a equals word "Path"
If "%%a"=="Path" (
If [%%c]==[] (
Echo %%b
) ELSE (
Echo %%b %%c
)
)
)
答案 1 :(得分:0)
如果可以在计算机上安装PowerShell模块,列出文件名就很容易了。这可以在任何受支持的现代Windows系统上完成。
https://www.powershellgallery.com/packages/7Zip4Powershell/1.9.0介绍了如何安装模块。
这是一个.bat文件脚本,显示其用法和输出。
C:>TYPE zipfnlist.bat
@ECHO OFF
SET "ZIP_FILENAME=.\7zIntf20.zip"
powershell -NoLogo -NoProfile -Command (Get-7Zip -ArchiveFileName "%ZIP_FILENAME%").FileName
C:>CALL zipfnlist.bat
bin
Properties
Ole32.cs
Program.cs
SevenZipFormat.cs
SevenZipInterface.cs
SevenZip.csproj
SevenZip.sln
bin\Debug
bin\Release
bin\Release\SevenZip.exe
Properties\AssemblyInfo.cs
答案 2 :(得分:0)
如果您不喜欢使用未记录的命令行开关的声音,您可以执行以下操作以从完整输出中解析出文件名。此 awk 脚本确定 Name
列标题的起始索引,并使用它从表中提取列。
awk_script='{
if (ix == 0) {
ix = index($0, "Name");
}
p = (body == 1);
if (ix > 0) {
# The table body is delimited by dashed lines, after the "Name" column header has been seen
body = (body + ($0 ~ / *-[ -]+/)) % 2;
}
if (p == 1 && body == 1) {
# Only print if "body" was 1 before and after the previous block; otherwise, we are in
# the table body delimiter line (or outside the table completely)
print substr($0, ix);
}
}'
7z l your-file.7z | awk "$awk_script"
PowerShell 等效:
$ix=-1;
$body=$false;
& 7z l your-file.7z | foreach { `
if ($ix -eq -1) {`
$ix = $_.IndexOf("Name");`
}`
$p = $body;`
if ($ix -gt 0) {`
# The table body is delimited by dashed lines, after the "Name" column header has been seen`
$body = ($body -ne ($_ -match ' *-[ -]+'))
}`
if ($p -and $body) {`
# Only print if "body" was 1 before and after the previous block; otherwise, we are in`
# the table body delimiter line (or outside the table completely)`
write-output $_.Substring($ix)`
}`
}
答案 3 :(得分:0)
我能够通过使用 -ba
标志为存档中的每个项目获取一行输出,然后使用 grep 解析每一行以仅获取文件名来实现此目的。
考虑这个例子,列出包含单个文件 baz
的档案的内容,该文件嵌套在两级目录 foo
和 bar
中。
user@host:~$ 7z l -ba 'archive.7z'
结果如下:
2021-06-21 14:37:09 D.... 0 0 foo
2021-06-21 14:37:41 D.... 0 0 foo/bar
2021-06-21 14:37:41 ....A 881 524 foo/bar/baz
然后,使用 grep 只获取每行末尾的路径:
user@host:~$ 7z l -ba 'archive.7z' | grep -oP '\S+$'
给出输出:
foo
foo/bar
foo/bar/user1.lnk
如果您想列出包括目录在内的所有项目,那么您就完成了上述操作。就我而言,我实际上是想预览将使用 7z e
提取的项目,它只提取没有目录结构的文件,所以我补充说:
user@host:~$ 7z l -ba 'archive.7z' | grep -vF 'D....' | grep -oP '\S+$' | xargs basename
这给出了我想要的输出;对于这个例子:
user1.lnk