「圧縮解除」が事前に単一のフォルダを作成しているかどうかはどうすればわかりますか?

「圧縮解除」が事前に単一のフォルダを作成しているかどうかはどうすればわかりますか?

一般的な状況は、他のタスクを含むディレクトリにzipファイルを含めることです。

me@work ~/my_working_folder $ ls
downloaded.zip  workfile1  workfile2  workfile3

解凍したいのですが、downloaded.zip混乱を招くのか、それとも自分のディレクトリを素敵に作成するのかわかりません。私が取り組んでいる解決策は、一時フォルダを作成してそのフォルダに解凍することです。

me@work ~/my_working_folder $ mkdir temp && cp downloaded.zip temp && cd temp
me@work ~/my_working_folder/temp $ ls
downloaded.zip
me@work ~/my_working_folder/temp $ unzip downloaded.zip 
Archive:  downloaded.zip
   creating: nice_folder/

これにより、my_working_folderzipファイルが大量のコンテンツで埋められるのを防ぎます。

私の質問は次のとおりです解凍する前にzipファイルにフォルダが1つしか含まれていないことを確認するより良い方法はありますか?

答え1

わかったできる無条件にサブディレクトリに抽出し、単一のエントリのみが含まれる場合は削除してください。

しかし、なぜ行くのですか?健全でシンプルなソリューション(頼るイルカチョ)、いつから使用できますかawk? :)

sunzip ()
{
    if [ $# -ne 1 ] || ! [ -f "$1" ]
    then
        printf '%s\n' "Expected a filename as the first (and only) argument. Aborting."
        return 1
    fi

    extract_dir="."

    # Strip the leading and trailing information about the zip file (leaving
    # only the lines with filenames), then check to make sure *all* filenames
    # contain a /.
    # If any file doesn't contain a / (i.e. is not located in a directory or is
    # a directory itself), exit with a failure code to trigger creating a new
    # directory for the extraction.
    if ! unzip -l "$1" | tail -n +4 | head -n -2 | awk 'BEGIN {lastprefix = ""} {if (match($4, /[^/]+/)) {prefix=substr($4, RSTART, RLENGTH); if (lastprefix != "" && prefix != lastprefix) {exit 1}; lastprefix=prefix}}'
    then
        extract_dir="${1%.zip}"
    fi

    unzip -d "$extract_dir" "$1"
}

速くて汚い。 InfoZIP unzipv6.0に適用されます。追加のパラメータを許可したり、自動的に使用したり、抽出サブディレクトリに別の名前(現在のファイル名で決定)を使用する
など、必要に応じてそれらを調整できます。unzipzip


ああ、この回避策が最も一般的な2つの場合(1. ZIPファイルにコンテンツを含むディレクトリが含まれている場合、2. ZIPファイルに複数の別々のファイルおよび/またはディレクトリが含まれている場合)は正しく処理されますが、ルートディレクトリが作成されないことを確認しました。 ZIPファイルには複数のディレクトリが含まれていますが、ファイルはありません。サブディレクトリは...

編集する:安定した。スクリプトawkはZIPファイルに含まれている各パスの最初のコンポーネント(「プレフィックス」)を保存し、以前のプレフィックスとは異なるプレフィックスが検出されるとすぐに中断されます。これは、すべてのコンテンツが同じサブディレクトリに含まれるZIPファイルを無視しながら、複数のファイルと複数のディレクトリ(両方とも名前が異なるため)をキャプチャします。

答え2

抽出する前にアーカイブの内容を確認するのではなく、次のコマンドを使用して抽出することもできます。unarこれは所望の動作を提供する。デフォルトでは、アーカイブに単一の最上位ディレクトリが含まれている場合はそのまま抽出され、unarそれ以外の場合はアーカイブ名のディレクトリを作成してそこから抽出します。このオプションを使用すると、すべての場合にディレクトリを強制的に作成できます-d

unarまた、さまざまなアーカイブ形式をサポートするという利点もあります。

答え3

マニュアルで...

[-d ディレクトリ]

ファイルを抽出するオプションのディレクトリです。デフォルトでは、すべてのファイルとサブディレクトリは現在のディレクトリに再作成されます。 -dオプションを使用すると、任意のディレクトリから抽出できます(そのディレクトリへの書き込み権限は常に仮定されます)。このオプションはコマンドラインの末尾に表示される必要はありません。 zipfile指定の前(通常オプションを使用)、zipfile指定の直後、またはファイルと-xオプションの間にも許可できます。オプションとディレクトリは空白なしで接続できますが、これは通常のシェルの動作を抑制する可能性があることに注意してください。特に -d ~(チルダ)はUnix Cシェルではユーザーのホームディレクトリ名に展開されますが、現在のディレクトリの文字通りサブディレクトリとして扱わ-d~れます。~

だから...

unzip -d new_dir zipfile.zip

これにより、new_dirディレクトリが作成され、その中にあるアーカイブが抽出されますので、最初に見ることなく、毎回潜在的な混乱を避けることができます。見てみるのも便利ですman unzipマニュアルページの追加ヘルプ

答え4

デフォルトの解凍を使用する素晴らしいbash oneライナーは次のとおりです。

 while read -r line; do (unzip -d "$(basename "$line" .zip)" "$line"); done < <(find . | grep '.zip')

抽出するzipファイルを含むディレクトリでこのコマンドを実行します。

  • < <結果をfind . | grep '.zip'ループに入力しますwhile
  • 返されたファイル名は次のようfindに保存されます。line
  • このwhileループはファイル名を繰り返してファイルline名をdo
  • これにより、次のファイル名を使用してdoディレクトリが作成されます。basename$line
    • 拡張子は、.zip文字列から削除するテキストとして指定されます。
    • 拡張子なしでファイル名のみを残します(デフォルト名!)
  • 新しいディレクトリの作成に使用 -dするデフォルト名を引数します。.zip
    • /folder/archive.zipすると待ちます/folder/archive/unzipped_file.txt
    • これはWindows / 7zipの「抽出先」オプションと非常によく似ています。
  • その後、この変数は$line解凍の対象として使用されます。

このライナーは様々なアイテムにも使えますよ!ファイル移動、ファイル圧縮、ファイルコピー...検索が再帰的で、とても便利です!

関連情報