Extracting nested zip files
This will extract all the zip files into the current directory, excluding any zipfiles contained within them.
find . -type f -name '*.zip' -exec unzip -- '{}' -x '*.zip' \;
Although this extracts the contents to the current directory, not all files will end up strictly in this directory since the contents may include subdirectories.
If you actually wanted all the files strictly in the current directory, you can run
find . -type f -mindepth 2 -exec mv -- '{}' . \;
Note: this will clobber files if there are two with the same name in different directories.
If you want to recursively extract all the zip files and the zips contained within, the following extracts all the zip files in the current directory and all the zips contained within them to the current directory.
while [ "`find . -type f -name '*.zip' | wc -l`" -gt 0 ]
do
find . -type f -name "*.zip" -exec unzip -- '{}' \; -exec rm -- '{}' \;
done
As far as I understand, you have zip archives that themselves contain zip archives, and you would like to unzip nested zips whenever one is extracted.
Here's a bash 4 script that unzips all zips in the current directory and its subdirectories recursively, removes each zip file after it has been unzipped, and keeps going as long as there are zip files. A zip file in a subdirectory is extracted relative to that subdirectory. Warning: untested, make a backup of the original files before trying it out or replace rm
by moving the zip file outside the directory tree.
shopt -s globstar nullglob
while set -- **/*.zip; [ $# -ge 1 ] do
for z; do
( cd -- "$(dirname "$z")" &&
z=${z##*/} &&
unzip -- "$z" &&
rm -- "$z"
)
done
done
The script will also work in zsh if you replace the shopt
line with setopt nullglob
.
Here's a portable equivalent. The termination condition is a little complicated because find
does not spontaneously return a status to indicate whether it has found any files. Warning: as above.
while [ -n "$(find . -type f -name '*.zip' -exec sh -c '
cd "${z%/*}" &&
z=${z##*/} &&
unzip -- "$z" 1>&2 &&
rm -- "$z" &&
echo 1
')" ]; do :; done