2008-09-20 2 views
43

Команда unzip не имеет возможности для рекурсивного распаковки архивов.Как вы рекурсивно распаковываете архивы в каталог и его подкаталоги из командной строки Unix?

Если у меня есть следующие структуры каталогов и архивы:

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

И я хочу, чтобы распаковать все архивы в директорию с таким же именем, как и каждый архив:

 
/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 

Что команд или команды я бы выпустил?

Важно, чтобы это не забивало имена файлов, в которых есть пробелы.

+0

Как насчет длинных путей к файлам ... за пределами 260 символов ...: https://superuser.com/a/1263234/439537 – Andrew 2017-10-28 06:13:49

ответ

59

Если вы хотите, чтобы извлечь файлы в соответствующую папку, вы можете попробовать этот

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

мульти-модифицированную версию для систем, которые могут справиться с высоким I/O:

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

Вот одно решение, которое включает в себя команды поиска и время цикла:

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

** ПРИМЕЧАНИЕ ** - это извлечение всех zip-файлов в рабочий каталог ** ! **, когда вы запросили относительную распаковку. см. [Ответ Вивека] (http://stackoverflow.com/a/2318189/3191896) – 2015-03-04 08:11:31

+0

Хм, похоже, он не распаковывает их все в рабочий каталог AFAICT. Я использую UnZip 5.52 от OS X El Capitan 10.11.6. Результаты, похоже, идентичны результатам Вивека. Принимая его ответ, хотя, так как он также показывает, как использовать несколько ядер! – chuckrector 2016-10-09 00:36:26

2

Что-то вроде Gunzip используя флаг -r ....

путешествия структура каталога рекурсивно?. Если любое из имен файлов, указанных в командной строке, это каталоги, gzip будет спускаться в каталог и сжимать все найденные там файлы (или распаковывать их в случае с gunzip).

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

+2

Он специально говорит о zip-файлах, а не о файлах gzip. – dvorak 2008-09-20 14:16:26

4

Вы можете использовать найти вместе с -exec флагом в одной командной строке, чтобы сделать работу

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

Это распаковывает все в текущий каталог, а не по отношению к каждому подкаталогу. Он также не распаковывается в каталог с тем же именем, что и каждый архив. – chuckrector 2008-09-20 12:31:52

0

Если вы используете Cygwin, синтаксис немного отличается для базового имени команда.

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

Я понимаю, что это очень старый, но это был один из первых хитов в Google, когда я искал решение чего-то подобного, поэтому я опубликую то, что я сделал здесь. Мой сценарий немного отличается, как я в основном просто хотел полностью взорвать банку вместе со всей баночкой, содержащейся в нем, так что я написал следующий Баш функции:

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" 
} 

Примечания к <file-where-this-function-is-stored>, которая необходима, если вы храните это в файле, который не читается для неинтерактивной оболочки, каким я оказался. Если вы храните функции в файле, загруженном на неинтерактивные оболочки (например, .bashrc, я полагаю), вы можете удалить весь оператор source. Надеюсь, это поможет кому-то.

Небольшое предупреждение - explodeFile также удаляет ziped-файл, вы можете, конечно, изменить это, комментируя последнюю строку.

10

Решение, которое корректно обрабатывает все имена файлов (включая символ новой строки) и извлекает в каталог, который находится в том же месте, что и файл, только с расширением удалены:

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

Заметим, что вы можете легко сделать это обрабатывать больше типов файлов (например, .jar), добавив их с помощью -o, например:

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

Другим интересным решением будет:

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; 
Смежные вопросы