94

Is it possible to replace a file in a zip file without unzipping deleting the old file adding the new file and rezipping it back?

Reason is I have a zip file which is really big there is one xml inside the zip file that I have to update sometimes. Unzipping the zip and rezipping it takes a long time. So I'd like to just be able to replace the one xml inside the zip through a script. I already have that checks for updates on the xml I have.

So is it possible to just replace the one xml without unzipping and rezipping ?

Sorry i would use the zip command to do things like that but 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 definately 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

Jayan
  • 16,628
  • 12
  • 79
  • 131
user577732
  • 3,626
  • 9
  • 50
  • 75

10 Answers10

77

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
  • 2,907
  • 1
  • 20
  • 17
66

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
  • 29,519
  • 6
  • 64
  • 94
  • 8
    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
58

Try the following:

zip [zipfile] [file to update] 

An example:

$ zip test.zip test/test.txt
updating: test/test.txt (stored 0%)
WizardsOfWor
  • 2,416
  • 25
  • 20
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
  • 892
  • 10
  • 19
12

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
  • 6,403
  • 2
  • 21
  • 28
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,798
  • 1
  • 16
  • 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
  • 12,356
  • 1
  • 28
  • 44
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
  • 4,162
  • 5
  • 43
  • 54
mzsolt
  • 51
  • 3
-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
  • 26,829
  • 23
  • 111
  • 159