Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I have a file named 'sourceZip.zip'

This file ('sourceZip.zip') contains two files:

'textFile.txt'

'binFile.bin'


I also have a file named 'targetZip.zip'

This file ('targetZip.zip') contains one file:

'jpgFile.jpg'


In linux, what bash command shall I use to copy both files ('textFile.txt', 'binFile.bin') from the source archive ('sourceZip.zip') straight into the second archive ('targetZip.zip'), so that at the end of the process, the second archive ('targetZip.zip') will include all three files?

(ideally, this would be done in one command, using 'zip' or 'unzip')

share|improve this question

migrated from stackoverflow.com Feb 18 '11 at 21:43

This question came from our site for professional and enthusiast programmers.

add comment

4 Answers 4

up vote 4 down vote accepted

Using the usual command-line zip tool, I don't think you can avoid separate extraction and update commands.

source_zip=$PWD/sourceZip.zip
target_zip=$PWD/targetZip.zip
temp_dir=$(mktemp -dt)
( cd "$temp_dir"
  unzip "$source_zip"
  zip -g "$targetZip" .
  # or if you want just the two files: zip -g "$targetZip" textFile.txt binFile.bin
)
rm -rf "$temp_dir"

There are other languages with more convenient zip file manipulation libraries. For example, Perl with Archive::Zip. Error checking omitted.

use Archive::Zip;
my $source_zip = Archive::Zip->new("sourceZip.zip");
my $target_zip = Archive::Zip->new("targetZip.zip");
for my $member ($source_zip->members()) {
          # or (map {$source_zip->memberNamed($_)} ("textFile.txt", "binFile.bin"))
    $target_zip->addMember($member);
}
$target_zip->overwrite();

Another way is to mount the zip files as directories. Mounting either of the zip files is enough, you can use zip or unzip on the other side. Avfs provides read-only support for many archive formats.

mountavfs
target_zip=$PWD/targetZip.zip
(cd "$HOME/.avfs$PWD/sourceZip.zip#" &&
 zip -g "$target_zip" .)  # or list the files, as above
umountavfs

Fuse-zip provides read-write access to zip archives, so you can copy the files with cp.

source_dir=$(mktemp -dt)
target_dir=$(mktemp -dt)
fuse-zip sourceZip.zip "$source_dir"
fuse-zip targetZip.zip "$target_dir"
cp -Rp "$source_dir/." "$target_dir" # or list the files, as above
fusermount -u "$source_dir"
fusermount -u "$target_dir"
rmdir "$source_dir" "$target_dir"

Warning: I typed these scripts directly in my browser. Use at your own risk.

share|improve this answer
    
thank you Gilles –  user3077 Feb 20 '11 at 15:35
add comment

Not sure about adding to archive, but you can always recreate one

unzip a.zip -d tmp
unzip b.zip -d tmp
zip -r c.zip tmp

First two lines unpack archives into tmp dir and the third one packages it back.

share|improve this answer
add comment

There's a tool called zipmerge that can do it. The description from the man page is:

zipmerge merges the source zip archives source-zip into the target zip archive target-zip. By default, files in the source zip archives over- write existing files of the same name in the target zip archive.

share|improve this answer
add comment

I'm going to say straightaway that I don't know the answer, from a practical point.

However, from a theoretical viewpoint, surely you'd have to unzip and re-zip the files. You can't just move them in zipped-state, surely? For a start, you'd have to assume that both zip files had identical settings with regard to compression mode and level.

You could possibly chain the unzip and zip commands together, but then that becomes a question of juggling around the commands on the command line, for which I shall defer to the *nix experts.

I stand very ready to be corrected.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.