如何在zip压缩文件中更新单个文件

124

是否可以在不解压缩的情况下替换zip文件中的文件?

需要更新的文件是一个位于大型zip归档文件中的XML文件。为了更新此XML文件,我必须先解压缩存档文件,删除旧的XML文件,添加新的XML文件,然后重新进行压缩。这需要相当长的时间。因此,希望能够通过脚本替换该XML文件。我已经有一个检查XML更新的脚本。

使用zip命令
很抱歉,我本来会使用zip命令来完成这样的事情,但问题在于该脚本实际上是针对安卓手机的,而zip不是我能够使用的命令,很抱歉我没有提到这一点。如果我能使用zip,我肯定会使用它,但我只有针对droid的unzip和busybox中的tar,但tar无法满足我的需求。


7
此外,这个问题本来可以只用一两个句子来表达。其中大约80%都是冗长无意义的陈述。 - Dennis Williamson
10个回答

94

请尝试以下方法:

zip [zipfile] [file to update] 

一个例子:

$ zip test.zip test/test.txt
updating: test/test.txt (stored 0%)

2
由于有示例,这是最容易理解的,谢谢! - anaotha
5
请注意,如果您想要更新压缩包中的文件,应该看到updating:而不是adding:。否则,您将向压缩包中添加文件,而不是将其替换。 - Edenshaw
1
对我来说,这个操作是将test/test.txt文件添加到test.zip根目录下。你知道如何指定test.txt文件所在的文件夹吗?我该如何添加test文件夹的内容而不是文件夹本身? - Vencovsky
1
进入测试目录并将 test.txt 压缩到 ../test.zip 以使其位于压缩文件的根目录。如果您想要一个不同命名的目录,请创建该目录,将 test.txt 放在其中,并按上述方法添加。 - WizardsOfWor

88

我发现对于替换zip文件中的单个文件,Linux的zip文件操作有些繁琐。Java开发工具包中的jar实用程序可能更容易使用。考虑在JAR文件(一个zip文件)中更新WEB/web.xml这个常见任务:

jar -uf path/to/myapp.jar -C path/to/dir WEB-INF/web.xml

这里,path/to/dir是包含WEB-INF目录(其中又包含web.xml)的目录的路径。


如果我只需要复制文件而不是创建一个名为WEB-INF的目录,该怎么办? - Helping hand
在我的情况下,亲爱的老“jar”工具派上了用场!谢谢! - bitfox
3
这个的性能如何?它是简单地创建一个包含每个文件和新文件的新存档并替换原始存档,还是实际上进行了一些就地操作的魔术? - AgentM
@Helpinghand 只需不输入 -C,而是键入文件名。这样只会替换您想要的文件。 - Investigator

72

来自zip(1)

给定现有 zip 存档的名称时,zip 命令会替换存档中同名的条目或为新名称添加条目。

因此,只需像平常一样使用 zip 命令创建一个包含一个文件的新 .zip 文件,除了你指定的 .zip 文件名将是现有存档。


10
可以请问有人举个例子吗?我不太明白 zip 命令的作用。 - Gustave
12
假设您使用命令 zip -r myfolder.zip myfolder 压缩了文件夹 myfolder,如果您想要更新 myfolder/otherfolder/myfile.txt,请编辑该文件并运行命令 zip -r myfolder.zip myfolder/otherfolder/myfile.txt - eakkas
1
如果要替换的文件与被替换的文件名称或结构不同,该如何操作? - Fractaliste
2
@Fractaliste 你必须让它具有相同的名称和结构 ;) - Hack5

19

使用更新标志:-u

例如:

zip -ur existing.zip myFolder

此命令将压缩并添加myFolder(及其内容)到existing.zip中。


高级用法:

实际上,更新标志会将传入的文件与现有文件进行比较,并添加新文件或更新现有文件。

因此,如果您想要添加/更新zip文件中的特定子目录,请按照需要更新源,然后使用-u标志重新压缩整个源。只有更改的文件将被压缩。

如果您无法访问源文件,则可以解压缩zip文件,然后更新所需文件,然后使用-u标志重新压缩。同样,只有更改的文件将被压缩。

例如:

原始源结构


ParentDir
├── file1.txt
├── file2.txt
├── ChildDir
│   ├── file3.txt
│   ├── Logs
│   │   ├── logs1.txt
│   │   ├── logs2.txt
│   │   ├── logs3.txt

更新后的源代码结构


ParentDir
├── file1.txt
├── file2.txt
├── ChildDir
│   ├── file3.txt
│   ├── Logs
│   │   ├── logs1.txt
│   │   ├── logs2.txt
│   │   ├── logs3.txt 
│   │   ├──<b> logs4.txt <i><-- NEW FILE </i></b>

使用方法

<b>$ zip -ur existing.zip ParentDir </b>
> updating: ParentDir/ChildDir/Logs (stored 0%)
>   adding: ParentDir/ChildDir/Logs/logs4.txt (stored 96%)

谢谢,这个方法可行。可能看起来有点不寻常,但我需要创建一个干净的文件夹,在其中进行工作,将zip文件复制到其中,然后在其中创建一系列嵌套的空目录,这些目录与zip文件中包含我想要替换的文件的名称相同!但它确实有效,当我执行unzip -l时,被替换文件的新文件大小证明了这一点。 - cardamom
您知道如何仅添加/更新文件夹的内容而不是文件夹本身吗? - Vencovsky

13

我知道这是一个旧问题,但我想做同样的事情。更新zip存档中的文件。以上所有答案都没有真正帮助到我。

这是我做的:创建了一个临时目录abc。将file.zip复制到abc并在该目录中提取文件。我编辑了想要编辑的文件。然后在abc中运行以下命令:

user@host ~/temp/abc $ zip -u file.zip
updating: content/js/ (stored 0%)
updating: content/js/moduleConfig.js (deflated 69%)

-u开关将查找已更改/新增的文件,并将其添加到zip存档中。


5
您可以使用以下命令: zip -u file.zip path/file_to_update

1
还有一个-f选项可以更新zip文件。它可以用于更新自压缩文件生成后已更新的所有文件(假设它们在zip文件中的树结构内的相同位置)。
如果您的文件名为/myfiles/myzip.zip,您只需要执行以下操作:
zip -f /myfiles/myzip.zip

0
从ZIP存档结构的角度来看,您可以在不重新压缩的情况下更新zip文件,您只需要跳过所有在您需要替换的文件之前的文件,然后放入您更新的文件,再加上剩余的文件。最后,您需要放入更新后的中央目录结构。 然而,我怀疑大多数常见工具是否允许您这样做。

0

7zip(7za)可用于很好地添加/更新文件/目录:

示例: 替换JAR文件中的MANIFEST.MF文件(无论文件日期如何)。/source/META-INF目录包含您要放入jar(zip)中的MANIFEST.MF文件:

7za a /tmp/file.jar /source/META-INF/

仅更新(如果源文件比目标文件旧,则不替换目标文件)

7za u /tmp/file.jar /source/META-INF/

-2

是的,这是可能的。

在基于Linux的系统上,只需安装zip即可在命令行中调用它。请查看manpage:http://linux.die.net/man/1/zip

但根据我的个人经验,如果可能且压缩并不那么重要,使用普通的tar文件和tar会更好。


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