it-roy-ru.com

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

Команда unzip не имеет возможности рекурсивно разархивировать архивы.

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

/Мать/Loving.Zip 
/Цинга/Sea Dogs.Zip 
/Цинга/Cures/Limes.Zip 

И я хочу разархивировать все архивы в каталоги с тем же именем, что и у каждого архива:

/Мать/Loving/1.txt 
/Мать/Loving.Zip 
/Цинга/Sea Dogs/2.txt 
/Цинга/Sea Dogs.Zip 
/Цинга/лекарства/Липки/3.txt 
/Цинга/лекарства/Limes.Zip 

Какую команду или команды я бы дал?

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

55
chuckrector

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

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

Многопроцессорная версия для систем, которые могут обрабатывать высокий уровень ввода-вывода:

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

Вот одно решение, которое включает команду find и цикл while:

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

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

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

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

find . '(' -name '*.Zip' -o -name '*.jar' ')' -exec ...
15
robinst

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

find . -name "*.Zip" -exec unzip {} \;
5
Jahangir

Что-то вроде gunzip с использованием флага -r? ....

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

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

2
essexboyracer

Это работает отлично, как мы хотим:

Распакуйте файлы:

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

Выше команда не создает дубликаты каталогов.

Удалить все файлы Zip:

find . -depth -name '*.Zip' -exec rm {} \;
1
Prabhav

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

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;
0
Prometheus

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

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

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

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 также удаляет заархивированный файл, вы, конечно, можете изменить это, закомментировав последнюю строку.

0
Thor84no