web-dev-qa-db-ja.com

Unixコマンドラインからディレクトリとそのサブディレクトリ内のアーカイブをどのように再帰的に解凍しますか?

unzipコマンドには、アーカイブを再帰的に解凍するオプションがありません。

次のディレクトリ構造とアーカイブがある場合:

/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 

どのコマンドを発行しますか?

これは、スペースが含まれるファイル名で詰まらないことが重要です。

56
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"'
89
Vivek Thomas

以下に、findコマンドとwhileループを含む1つのソリューションを示します。

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

すべてのファイル名(改行を含む)を正しく処理し、ファイルと同じ場所にあるディレクトリに抽出し、拡張子を削除しただけのソリューション:

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

.jarを使用して追加すると、より多くのファイルタイプ(-oなど)を簡単に処理できることに注意してください。

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

1つのコマンドラインで-execフラグと共にfindを使用して、ジョブを実行できます。

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

-rフラグを使用したgunzipのようなものですか?....

ディレクトリ構造を再帰的に移動します。コマンドラインで指定されたファイル名のいずれかがディレクトリの場合、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で最初にヒットしたものの1つだったので、ここで行ったことを投稿します。私のシナリオはわずかに異なります。基本的に、jarファイルとその中に含まれるすべてのjarファイルを完全に分解したかったため、次の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もzipファイルを削除します。もちろん、最後の行をコメントアウトすることで変更できます。

0
Thor84no