123

Is it possible to replace a file in a zip file without unzipping?

The file to update is an XML file that resides in a huge zip archive. To update this XML file, I have to unzip the archive, delete the old XML file, add the new one and then rezip. This takes a considerable amount of time. So want to be able to replace that one XML through a script. I already have the one that checks for updates on the XML I have.

using zip command
Sorry, I would use the zip command to do things like that but the problem is the script is actually for an android phone and zip is not a command I can use unfortunately sorry I left that out. I would have used zip definitely if i could but I only have unzip for droid and then there is tar in busybox but tar doesn't do what I need

rohitt
  • 1,124
  • 6
  • 18
user577732
  • 3,956
  • 11
  • 55
  • 76

10 Answers10

92

Try the following:

zip [zipfile] [file to update] 

An example:

$ zip test.zip test/test.txt
updating: test/test.txt (stored 0%)
WizardsOfWor
  • 2,974
  • 29
  • 23
  • 2
    This is the easiest one to understand thanks to the example, thanks! – anaotha Mar 01 '17 at 17:05
  • 5
    Take into account that you should see `updating:` instead of `adding:` if you want to update a file inside the zip; otherwise you are adding files to the zip, not replacing it. – Edenshaw Mar 12 '19 at 18:59
  • 1
    For me, what this does is add the entire `test/test.txt` file inside the root folder of `test.zip`. Do you know how to specify the folder where the `test.txt` file will be inside? How can I add the content of the `test` folder and not the folder itself? – Vencovsky Sep 08 '22 at 14:56
  • cd into the test directory and zip ../test.zip test.txt to put test.txt at the root of the zip. If you want a different named directory make it and put test.txt in there and add as above. – WizardsOfWor Feb 09 '23 at 03:40
87

I've found the Linux zip file to be cumbersome for replacing a single file in a zip. The jar utility from the Java Development Kit may be easier. Consider the common task of updating WEB/web.xml in a JAR file (which is just a zip file):

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

Here, path/to/dir is the path to a directory containing the WEB-INF directory (which in turn contains web.xml).

cayhorstmann
  • 3,192
  • 1
  • 25
  • 17
  • what if I have to copy only the file instead of creating a director `WEB-INF` which has that file. – Helping hand Mar 04 '19 at 14:03
  • Also in my case, the dear old "jar" util did the trick! Thanks! – bitfox Aug 19 '19 at 22:47
  • 3
    What is the performance of this? Does it simply create a new archive with every file and the new file and replace the original. Or does it actually do some in-place magic? – AgentM Aug 30 '21 at 19:34
  • @Helpinghand simply do not enter the -C and instead type the filename. That should replace only the file that you want. – Investigator Jan 13 '23 at 15:13
72

From zip(1):

When given the name of an existing zip archive, zip will replace identically named entries in the zip archive or add entries for new names.

So just use the zip command as you normally would to create a new .zip file containing only that one file, except the .zip filename you specify will be the existing archive.

PleaseStand
  • 31,641
  • 6
  • 68
  • 95
  • 10
    Could someone give an example, please? I don't understand the help of the zip command. – Gustave Jul 22 '15 at 10:08
  • 12
    Let's say you zipped myfolder using `zip -r myfolder.zip myfolder` if you want to update `myfolder/otherfolder/myfile.txt`, go ahead and edit the file and run `zip -r myfolder.zip myfolder/otherfolder/myfile.txt` – eakkas Jun 08 '16 at 21:50
  • 1
    How to do that if the file to replace has not the same name nor the same structure that the file to be repalced? – Fractaliste Apr 11 '17 at 09:55
  • 2
    @Fractaliste You have to make it have the same name and structure ;) – Hack5 Oct 17 '17 at 18:41
19

Use the update flag: -u

Example:

zip -ur existing.zip myFolder

This command will compress and add myFolder (and it's contents) to the existing.zip.


Advanced Usage:

The update flag actually compares the incoming files against the existing ones and will either add new files, or update existing ones.

Therefore, if you want to add/update a specific subdirectory within the zip file, just update the source as desired, and then re-zip the entire source with the -u flag. Only the changed files will be zipped.

If you don't have access to the source files, you can unzip the zip file, then update the desired files, and then re-zip with the -u flag. Again, only the changed files will be zipped.

Example:

Original Source Structure


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

Updated Source Structure


ParentDir
├── file1.txt
├── file2.txt
├── ChildDir
│   ├── file3.txt
│   ├── Logs
│   │   ├── logs1.txt
│   │   ├── logs2.txt
│   │   ├── logs3.txt 
│   │   ├── logs4.txt &lt-- NEW FILE 

Usage

$ zip -ur existing.zip ParentDir 
> updating: ParentDir/ChildDir/Logs (stored 0%)
>   adding: ParentDir/ChildDir/Logs/logs4.txt (stored 96%)
Ethan Strider
  • 7,849
  • 3
  • 24
  • 29
  • Thanks, this worked. May seem a bit of an unusual exercise, but I needed to create a clean folder to do this work in, copy the zip to it, then create a series of nested empty directories in it with the same names as the one in the zip containing the file I wanted to replace! But it worked, as evidenced in the new file size of the replaced file when I did `unzip -l` – cardamom Sep 28 '21 at 11:43
  • Do you know how to add/update only the contents of the folder and not the folder itself? – Vencovsky Sep 08 '22 at 15:17
13

I know this is old question, but I wanted to do the same. Update a file in zip archive. And none of the above answers really helped me.

Here is what I did. Created temp directory abc. Copied file.zip to abc and extracted the file in that directory. I edited the file I wanted to edit. Then while being in abc, ran the following command

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

-u switch will look for changed/new files and will add to the zip archive.

traditional
  • 942
  • 10
  • 19
5

You can use: zip -u file.zip path/file_to_update

1

There is also the -f option that will freshen the zip file. It can be used to update ALL files which have been updated since the zip was generated (assuming they are in the same place within the tree structure within the zip file).

If your file is named /myfiles/myzip.zip all you have to do is

zip -f /myfiles/myzip.zip
W7GVR
  • 1,990
  • 1
  • 18
  • 24
0

From the side of ZIP archive structure - you can update zip file without recompressing it, you will just need to skip all files which are prior of the file you need to replace, then put your updated file, and then the rest of the files. And finally you'll need to put the updated centeral directory structure. However, I doubt that most common tools would allow you to make this.

Nickolay Olshevsky
  • 13,706
  • 1
  • 34
  • 48
0

7zip (7za) can be used for adding/updating files/directories nicely:

Example: Replacing (regardless of file date) the MANIFEST.MF file in a JAR file. The /source/META-INF directory contains the MANIFEST.MF file that you want to put into the jar (zip):

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

Only update (does not replace the target if the source is older)

7za u /tmp/file.jar /source/META-INF/
Xpleria
  • 5,472
  • 5
  • 52
  • 66
mzsolt
  • 61
  • 4
-2

yes its possible.

on linux based systems just install zip and you can call it in the command line. have a look at the manpage: http://linux.die.net/man/1/zip

but in my personal experience, if possible and compression is not so important, this works better with plain tar files and tar.

The Surrican
  • 29,118
  • 24
  • 122
  • 168