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
どのようなコマンドを発行すればよいでしょうか?
スペースが含まれるファイル名で障害が発生しないことが重要です。
解決
ファイルをそれぞれのフォルダーに抽出したい場合は、これを試すことができます
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"'
他のヒント
find コマンドと while ループを使用した解決策の 1 つを次に示します。
find . -name "*.zip" | while read filename; do unzip -o -d "`basename -s .zip "$filename"`" "$filename"; done;
すべてのファイル名 (改行を含む) を正しく処理し、拡張子を削除しただけでファイルと同じ場所にあるディレクトリに抽出するソリューション:
find . -name '*.zip' -exec sh -c 'unzip -o -d "${0%.*}" "$0"' '{}' ';'
より多くのファイル タイプ ( .jar
) を使用して追加します -o
, 例:
find . '(' -name '*.zip' -o -name '*.jar' ')' -exec ...
単一のコマンドラインで find と -exec フラグを使用してジョブを実行できます。
find . -name "*.zip" -exec unzip {} \;
-r フラグを使用した Gunzip のようなものですか?....
ディレクトリ構造を再帰的に移動します。コマンドラインで指定されたファイル名のいずれかがディレクトリである場合、 gzip はそのディレクトリに降りて、そこで見つかったすべてのファイルを圧縮します (または、gunzip の場合は解凍します)。
これは私たちが望むように完全に機能します。
ファイルを解凍します。
find . -name "*.zip" | xargs -P 5 -I FILENAME sh -c 'unzip -o -d "$(dirname "FILENAME")" "FILENAME"'
上記のコマンドでは、重複したディレクトリは作成されません。
すべての zip ファイルを削除します。
find . -depth -name '*.zip' -exec rm {} \;
cygwin を使用している場合、basename コマンドの構文は少し異なります。
find . -name "*.zip" | while read filename; do unzip -o -d "`basename "$filename" .zip`" "$filename"; done;
これが非常に古いことは承知していますが、同様の解決策を探していたときに 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 ファイルも削除されますが、最終行をコメントアウトすることで変更することもできます。
別の興味深い解決策は次のとおりです。
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;