66

I sometimes need to make changes to a .zip or .jar file, so I usually move the file to /tmp, extract all the files with unzip, edit a few files, and then re-zip up the files. This works, but it can be tedious. Is there a utility or shell script that I can use to edit a file inside of a zip file without explicitly calling unzip and zip (even if it's just a wrapper around these commands)?

austin
  • 928
  • 1
  • 6
  • 9
  • Just curious if the answer works on .jar files? (I didn't test it there.) – beroe Sep 24 '13 at 02:31
  • @beroe It should since those use the zip compression algorithm. That was actually my main motivation for looking for a solution because I had .war files deployed on an app server that I didn't feel like re-packaing up and re-deploying just to modify a single file. – austin Sep 24 '13 at 14:41
  • Great. I am going to try to fix the function so it preserves directory structure inside the archive. Currently I think it only works on files at root level, but for my purposes, subfolders are more useful. – beroe Sep 24 '13 at 14:45
  • @beroe That's pretty cool. Before asking this, I was going to code up a python script for launching a psudo-shell "inside" the zip file to execute arbitrary commands. I'd be interested in what you come up with. – austin Sep 24 '13 at 14:47
  • OK, added another solution to support sub-folders, and it works in *limited* testing. – beroe Sep 24 '13 at 19:37

8 Answers8

80

Vim supports transparently editing files inside zip files. Just execute:

vim file.zip

and you will be shown a list of files inside zip archive. Choose the one you want to edit, change what you want, and exit with :x

If vim responds with:

Cannot make changes, 'modifiable' is off

.. just run :set modifiable or :set ma (source: https://stackoverflow.com/questions/5745506/vim-modifiable-is-off)

javabrett
  • 484
  • 4
  • 10
jesjimher
  • 950
  • 1
  • 6
  • 5
  • 2
    By the way, default zip support in vim only allows editing one level ZIPs. If you need to edit ZIPs inside ZIPs, you should use [this vim plugin](http://www.vim.org/scripts/script.php?script_id=2206). – jesjimher May 14 '14 at 08:27
  • 2
    Same with emacs. – Mike Sep 02 '15 at 12:45
  • 8
    This should be marked as the right answer – Martijn Burger Feb 18 '16 at 14:37
  • 3
    life saver. really cool feature of vim, and quite unexpected too – Peter Perháč Aug 09 '16 at 08:15
  • 1
    Also, if you get the buftype issue, issue the comman `:set bt=` and then you can save. – JonShipman Apr 20 '20 at 13:25
  • Nice, it even works with `vimdiff a.zip b.zip` in order to compare the contents. – Eric Duminil Dec 13 '20 at 19:48
  • Is there a way to specify a full path to a file inside the zip archive to edit it right away (without the need to select it interactively)? For example, if the zip is an EPUB and it includes ``text/file.html`` file, I would want to do something like ``myepub.epub:text/file.html`` or ``myepub.epub/text/file.text``. I need this to modify a file inside ZIP non-interactively (through vim script like this: https://unix.stackexchange.com/a/14221/48886) but it would be useful if the same file needs to be modified interactively in different archives. – Rafal Sep 27 '21 at 13:38
  • This is what I was looking for. I did not think about vim to the trick for me. Thank you @jesjimher – jsmtslch Oct 06 '22 at 03:33
24

Do you know the name of the file in the archive before unzipping it? You could make a function to unzip to /tmp, edit, and refresh the zip:

zipedit(){
    echo "Usage: zipedit archive.zip file.txt"
    unzip "$1" "$2" -d /tmp 
    vi /tmp/$2 && zip -j --update "$1"  "/tmp/$2" 
}

As it says, usage is:

zipedit myarchive.zip myfile.txt

This unpacks the named file from the archive, saves it to /tmp, edits it in vi then adds it back to the archive, while "junking" the path. Add to your .bash_profile, assuming bash...

EDIT: Below is a version which works with subfolders inside the archive... Note, do not use a slash before the name of the folder (i.e. use myfolder/file.txt not /myfolder/file.txt). If you edit a file that didn't already exist in the archive, it will create it for you. Also not sure if it will work with the absolute path to the zip file. Best stick with relative.

zipedit(){
    echo "Usage: zipedit archive.zip folder/file.txt"
    curdir=$(pwd)
    unzip "$1" "$2" -d /tmp 
    cd /tmp
    vi "$2" && zip --update "$curdir/$1"  "$2" 
    # remove this line to just keep overwriting files in /tmp
    rm -f "$2" # or remove -f if you want to confirm
    cd "$curdir"
}

Thanks for the question. I'll probably end up using this one too!

Another edit: Untested, but I read that vim and emacs will both edit jar files directly?

beroe
  • 1,147
  • 7
  • 18
6

Short answer: NO.

If it's a wrapper, you are calling these commands. Anyway, the best I can think of is to open the file using file-roller, if you are in an X environment, that might work with a simple double click, depending on your setup. You can then double click on the compressed file to open it and then you can edit it:

$ file-roller b3.zip 

When you save your edited file, you should get this dialog:

You could make a script for this also, but that gets complicated if you have compressed archives that contain multiple files. Let me know if that's what you need and I might be able to cook something up.

enter image description here

terdon
  • 52,568
  • 14
  • 124
  • 170
3

Short pedantic answer; no. If you think about compression, you're using redundancy to shorten the files inside, so any edit changes the whole file within the archive, possibly the archive.

If you're being less theoretical, more practical, more "I don't want to have to manually unzip/zip" there are tools that you can use. ark on Linux is one I've used. You could also mount the archive with fuse-zip, though that's probably more work than a temp file.

Rich Homolka
  • 31,057
  • 6
  • 55
  • 80
1

Directory Opus 12 file manager will allow you to browse the Zip, then drag and drop the edited file from another folder into it and overwrite the file you want to edit, and it will do it all on the fly. Very easy

0

According to the man page for zip (online version for easy reference: http://linux.die.net/man/1/zip), the zip command has a -u flag which it describes as:

Replace (update) an existing entry in the zip archive only if it has been modified more recently than the version already in the zip archive.

Proctor
  • 9
  • 1
0

I wrote a Vim plugin that extends stock zip.vim to browse and edit nested zip files.

https://github.com/lbrayner/vim-rzip

0

You can use standart KDE text editor for example:

  1. open archive in archive manager
  2. open text file in KDE gui editor
  3. save text file and system ask you to refresh archive - click yes
  4. don't forget about permission for archive and folder of archive (my favorite mistake)
Pierre.Vriens
  • 1,415
  • 38
  • 16
  • 20
tvorez
  • 1