zipアーカイブに複数のファイルが含まれている場合にディレクトリを作成する


8

アーカイブのルートディレクトリに複数のファイルが含まれている場合、ファイル名にちなんで名付けられたディレクトリ(拡張子なし)を作成します。アーカイブにディレクトリのみが含まれている場合は、単にそれを抽出します。次のアーカイブがあるとします。

# file: withdir.zip
somedir/alpha
somedir/beta
somedir/gamma

現在のディレクトリに抽出した場合、単純に抽出したい(unzip withdir.zip):

somedir/alpha
somedir/beta
somedir/gamma

次のアーカイブを想定します。

# file: nodir.zip
alpha
beta
gamma

実行するunzip nodir.zipと、3つのファイルで現在のディレクトリが乱雑になってしまいます。

alpha
beta
gamma

私はむしろ実行したいunzip -d nodir nodir.zip

nodir/alpha
nodir/beta
nodir/gamma

nautilusを使用していて、[ここで抽出]を右クリックした場合。正しく動作します。しかし残念ながら、私はのためのコマンドラインスイッチ見つかっていないunzipか、 7z同じ動作をもたらします。それを達成する方法は?代わりに使用できる他のツールはありますか(GUIなし)?

回答:


7

私はこのようなことをします(zsh構文):

unz() (
  tmp=$(TMPDIR=. mktemp -d -- ${${argv[-1]:t:r}%.tar}.XXXXXX) || exit
  print -r >&2 "Extracting in $tmp"
  cd -- $tmp || exit
  [[ $argv[-1] = /* ]] || argv[-1]=../$argv[-1]
  (set -x; "$@"); ret=$?
  files=(*(ND[1,2]))
  case $#files in
    (0) print -r >&2 "No file created"
        rmdir -v "../$tmp";;
    (1) mv -v -- $files .. && rmdir -v ../$tmp;;
    (*) mv -vT ../$tmp ../$tmp:r;;
  esac && exit $ret
)

あれは:

  1. とにかくディレクトリを作成する
  2. コマンドを実行する
  3. コマンドが生成したファイルの数に応じて:
    • そのディレクトリを削除します(ファイルが作成されなかった場合)
    • ファイル/ディレクトリが1つしか作成されていない場合は、1レベル上に移動してディレクトリを破棄します
    • それ以外の場合は、一時ディレクトリの最後からランダムな文字列を削除してみます。

このようにして、次のことができます。

unz unzip foo.zip
unz tar xf foo.tar.gz

抽出コマンドの最後の引数は抽出するファイルであると想定しています。また、-vオプションのGNUツールを想定しています。非GNUシステムでは、それらを削除して、おそらく手動でロギングを行うことができます。mv -Tまた、GNU固有でありmv、名前の変更のみを試みるように強制します。


3

通りunzip7z両方指定されたディレクトリに出力するスイッチを持っている、あなたがチェックは、どのように多くのファイルがアーカイブのルートにあり、その後、必要に応じてスイッチを追加することを、簡単なスクリプトを作成することができます。

7z -sltでは、出力がより機械的に読みやすくなるスイッチがあるため、これはより簡単です。zip内のすべてのファイルについて、出力には1 Path = ...行が含まれます。ルートのファイルには/、値が含まれていてはなりません。

その方法でファイルを解凍するために書いた簡単なスクリプト:

#!/bin/sh
for archive in "$@"; do
    # count files in root dir
    rootfiles=$(7z l -slt "${archive}" | grep -c 'Path = [^/]*$')

    # add -o switch, if more than one file in root
    # checks for >2, because path of the zip file itself is listed too
    if [ $rootfiles -gt 2 ]; then
        filename=${archive##*/}
        rootname=${filename%.*}
        opt="-o${rootname}"
    fi

    #unpack
    7z x "${opt}" "${archive}"
done

編集:スクリプトがzipでも動作するようになりました


このスクリプトは期待どおりに動作しません。はを返すため、ルートには1つのディレクトリしか含まれていませんがwithdir、アーカイブ用のディレクトリを作成します。withdir.zipgrep -c "Folder = -"3
マルコ

ああ、zipファイルではフォルダが違うようです。私は修正を探します
crater2150 2013

@Marco:スクリプトを変更してzipファイルでテストしましたが、必要な場合にのみフォルダーが作成されるようになりました
crater2150

3

patoolはさまざまな種類のアーカイブを処理し、アーカイブに複数のファイルが含まれている場合にサブディレクトリを作成して、抽出されたファイルで作業ディレクトリが乱雑にならないようにします。

アーカイブを作成

patool create archive.zip somedirectory

アーカイブを抽出

patool extract archive.zip

サポートされている形式のリストを取得するには、を使用しますpatool formats


1

unarを使用することもできます。これにより、2つ以上のトップレベルファイルがある場合、デフォルトで格納ディレクトリが作成されます。

$ touch 1 2
$ zip a.zip 1 2
  adding: 1 (stored 0%)
  adding: 2 (stored 0%)
$ unzip -l a.zip
Archive:  a.zip
  Length     Date   Time    Name
 --------    ----   ----    ----
        0  04-29-14 10:56   1
        0  04-29-14 10:56   2
 --------                   -------
        0                   2 files
$ unar a.zip
a.zip: Zip
  1  (0 B)... OK.
  2  (0 B)... OK.
Successfully extracted to "a".
$ ls a
1 2

-d常に包含ディレクトリを作成するために追加します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.