If your unix variant supports FUSE (Linux, *BSD, OSX, Solaris all do), mount AVFS to access archives transparently. The command mountavfs creates a view of the whole filesystem, rooted at ~/.avfs, in which archive files have an associated directory that contains the directories and files in the archive. For example, if you have foo.zip in the current directory, then the following command is roughly equivalent to unzip -l foo.zip:
mountavfs # needs to be done once and for all
find ~/.avfs$PWD/foo.zip\# -ls
So, to loop over all images contained in a zip file under the current directory and copy them to /destination/directory (with a prompt in case of clash):
find ~/.avfs"$PWD" -name '*.zip' -exec sh -c '
find "${0}#" -name "*.jpg" -exec cp -ip {} "$1" \;
' {} /destination/directory \;
In zsh:
cp -ip ~/.avfs$PWD/**/*.zip(e\''REPLY=($REPLY\#/**/*.jpg(N))'\') /destination/directory
Deconstruction: ~/.avfs$PWD/**/*.zip expands to the AVFS view of the zip files under the current directory. The glob qualifier e is used to modify the output of the glob: …/*.zip(e\''REPLY=$REPLY\#'\') would just append a # to each match. REPLY=($REPLY\#/**/*.jpg(N)) transforms each match into the array of .jpg files in the .zip# directory.
zip -sf foo.zip | grep abc.jpgto determine if an archive hasabc.jpg; that should help. I don't have time to figure out the complete command now, but I'll try later if nobody else has answered – Michael Mrozek♦ Apr 26 '11 at 13:46