How do you recursively unzip archives in a directory and its subdirectories from the Unix command-line?

梦想的初衷 提交于 2019-12-17 17:33:12

问题


The unzip command doesn't have an option for recursively unzipping archives.

If I have the following directory structure and archives:

/Mother/Loving.zip
/Scurvy/Sea Dogs.zip
/Scurvy/Cures/Limes.zip

And I want to unzip all of the archives into directories with the same name as each archive:

/Mother/Loving/1.txt
/Mother/Loving.zip
/Scurvy/Sea Dogs/2.txt
/Scurvy/Sea Dogs.zip
/Scurvy/Cures/Limes/3.txt
/Scurvy/Cures/Limes.zip

What command or commands would I issue?

It's important that this doesn't choke on filenames that have spaces in them.


回答1:


If you want to extract the files to the respective folder you can try this

find . -name "*.zip" | while read filename; do unzip -o -d "`dirname "$filename"`" "$filename"; done;

A multi-processed version for systems that can handle high I/O:

find . -name "*.zip" | xargs -P 5 -I fileName sh -c 'unzip -o -d "$(dirname "fileName")/$(basename -s .zip "fileName")" "fileName"'



回答2:


Here's one solution that involves the find command and a while loop:

find . -name "*.zip" | while read filename; do unzip -o -d "`basename -s .zip "$filename"`" "$filename"; done;



回答3:


A solution that correctly handles all file names (including newlines) and extracts into a directory that is at the same location as the file, just with the extension removed:

find . -name '*.zip' -exec sh -c 'unzip -o -d "${0%.*}" "$0"' '{}' ';'

Note that you can easily make it handle more file types (such as .jar) by adding them using -o, e.g.:

find . '(' -name '*.zip' -o -name '*.jar' ')' -exec ...



回答4:


You could use find along with the -exec flag in a single command line to do the job

find . -name "*.zip" -exec unzip {} \;



回答5:


Something like gunzip using the -r flag?....

Travel the directory structure recursively. If any of the file names specified on the command line are directories, gzip will descend into the directory and compress all the files it finds there (or decompress them in the case of gunzip ).

http://www.computerhope.com/unix/gzip.htm




回答6:


This works perfectly as we want:

Unzip files:

find . -name "*.zip" | xargs -P 5 -I FILENAME sh -c 'unzip -o -d "$(dirname "FILENAME")" "FILENAME"'

Above command does not create duplicate directories.

Remove all zip files:

find . -depth -name '*.zip' -exec rm {} \;



回答7:


If you're using cygwin, the syntax is slightly different for the basename command.

find . -name "*.zip" | while read filename; do unzip -o -d "`basename "$filename" .zip`" "$filename"; done;



回答8:


I realise this is very old, but it was among the first hits on Google when I was looking for a solution to something similar, so I'll post what I did here. My scenario is slightly different as I basically just wanted to fully explode a jar, along with all jars contained within it, so I wrote the following bash functions:

function explode {
    local target="$1"
    echo "Exploding $target."
    if [ -f "$target" ] ; then
        explodeFile "$target"
    elif [ -d "$target" ] ; then
        while [ "$(find "$target" -type f -regextype posix-egrep -iregex ".*\.(zip|jar|ear|war|sar)")" != "" ] ; do
            find "$target" -type f -regextype posix-egrep -iregex ".*\.(zip|jar|ear|war|sar)" -exec bash -c 'source "<file-where-this-function-is-stored>" ; explode "{}"' \;
        done
    else
        echo "Could not find $target."
    fi
}

function explodeFile {
    local target="$1"
    echo "Exploding file $target."
    mv "$target" "$target.tmp"
    unzip -q "$target.tmp" -d "$target"
    rm "$target.tmp"
}

Note the <file-where-this-function-is-stored> which is needed if you're storing this in a file that is not read for a non-interactive shell as I happened to be. If you're storing the functions in a file loaded on non-interactive shells (e.g., .bashrc I believe) you can drop the whole source statement. Hopefully this will help someone.

A little warning - explodeFile also deletes the ziped file, you can of course change that by commenting out the last line.




回答9:


Another interesting solution would be:

DESTINY=[Give the output that you intend]

# Don't forget to change from .ZIP to .zip.
# In my case the files were in .ZIP.
# The echo were for debug purpose.

find . -name "*.ZIP" | while read filename; do
ADDRESS=$filename
#echo "Address: $ADDRESS"
BASENAME=`basename $filename .ZIP`
#echo "Basename: $BASENAME"
unzip -d "$DESTINY$BASENAME" "$ADDRESS";
done;


来源:https://stackoverflow.com/questions/107995/how-do-you-recursively-unzip-archives-in-a-directory-and-its-subdirectories-from

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!