Como você recursivamente arquivos descompactar em um diretório e seus subdiretórios a partir da linha de comando do Unix?

StackOverflow https://stackoverflow.com/questions/107995

  •  01-07-2019
  •  | 
  •  

Pergunta

O comando unzip não tem uma opção para recursivamente descompactar arquivos.

Se eu tiver a seguinte estrutura de diretórios e arquivos:

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

E eu quero para descompactar todos os arquivos em diretórios com o mesmo nome de cada arquivo:

/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

O comando ou comandos que eu iria emitir?

É importante que isso não engasgar com nomes de arquivos que têm espaços.

Foi útil?

Solução

Se você deseja extrair os arquivos para a pasta respectiva você pode tentar este

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

Uma versão multi-processados ??para sistemas que podem lidar com alta I / O:

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

Outras dicas

Aqui está uma solução que envolve o comando find e um tempo loop:

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

Uma solução que maneja bem todos os nomes de arquivo (incluindo novas linhas) e extratos em um diretório que está no mesmo local que o arquivo, apenas com a extensão removidos:

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

Note que você pode facilmente torná-lo lidar com mais tipos de arquivos (como .jar), adicionando-os usando -o, por exemplo:.

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

Você pode usar encontrar junto com a bandeira -exec em uma única linha de comando para fazer o trabalho

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

Algo como gunzip usando o sinalizador -r? ....

Viagens a estrutura de diretórios de forma recursiva. Se qualquer um dos nomes de arquivos especificados na linha de comando são diretórios, gzip descerá ao diretório e compactar todos os arquivos que ele encontra lá (ou descompactá-los no caso de gunzip).

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

Isso funciona perfeitamente como nós queremos:

descompactar arquivos:

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

Acima de não criar diretórios duplicados.

remover todos os arquivos zip:

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

Se você estiver usando cygwin, a sintaxe é um pouco diferente para o comando basename.

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

Sei que isso é muito antiga, mas foi um dos primeiros hits no Google, quando eu estava à procura de uma solução para algo semelhante, então eu vou postar o que eu fiz aqui. Meu cenário é um pouco diferente como eu basicamente só queria explodir completamente um frasco, juntamente com todos os frascos nela contido, então eu escrevi as seguintes funções festança:

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

Observe o <file-where-this-function-is-stored> que é necessário se você está armazenando isso em um arquivo que não é lido por um shell não interativo, como aconteceu de eu estar. Se você está armazenando as funções em um arquivo carregado em cascas de não-interativas (por exemplo, .bashrc creio eu) você pode deixar cair toda a declaração source. Esperemos que isto irá ajudar alguém.

Um aviso pouco -. explodeFile também exclui o arquivo ziped, você pode de mudança de curso que comentando a última linha

Outra solução interessante seria:

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;
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top