web-dev-qa-db-ja.com

独自のフォルダーにファイルを再帰的にZipするにはどうすればよいですか?

次のディレクトリ構造があります。

/Data
 - file 1
 - file 2

  /Folder1

   - file 3
   - file 4

  /Folder2
   - file 5
   - file 6

    /Folder3
      - file 7
      - file 8

Linuxでは、すべてのディレクトリでファイル(フォルダーを除く)を圧縮し、各フォルダーに7z(またはZip)アーカイブを作成して、次のようにします。

/Data
     Data.7z (Note: this should contain only file1 & 2, not any sub directories)

      /Folder1

       Folder1.7z (this should contain only file3 & 4, not any sub directories)

      /Folder2
       Folder2.7z (this should contain only file5 & 6, no Folder3)

        /Folder3
          Folder3.7z (should contain only file7 & 8)

次のスクリプトは最初のディレクトリで機能しますが、サブディレクトリでは機能しません。

for i in */ ; do base=$(basename “$i”) ; cd $base ; 7za a -t7z -r $base * ; .. ; cd .. ; done;

どうすればこれを達成できますか?

1
alien250

7zを使用する場合は、トリッキーな部分が再帰を説得しているようですnot。ドキュメントに示されている-r-スイッチは機能していないようであり、推奨される ソフトウェアの作成者による回避策 は、ワイルドカード表現-x!*/を含むサブディレクトリを除外することです

だから、与えられた

$ tree Data
Data
├── file1
├── file2
├── Folder1
│   ├── file3
│   └── file4
├── Folder2
│   ├── file5
│   └── file6
└── Folder3
    ├── file7
    └── file8

3 directories, 8 files

それから

find Data -type d -execdir sh -c 'cd "$1" && 7z a "$1".7z -x!*/ && cd -' sh {} \;

結果として

$ tree Data
Data
├── Data.7z
├── file1
├── file2
├── Folder1
│   ├── file3
│   ├── file4
│   └── Folder1.7z
├── Folder2
│   ├── file5
│   ├── file6
│   └── Folder2.7z
└── Folder3
    ├── file7
    ├── file8
    └── Folder3.7z

3 directories, 12 files

たとえば、次を使用してFolder2.7zが独自のフォルダのファイルのみを含むことを確認できます

$ 7z l Data/Folder2/Folder2.7z 

7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7Zip Version 16.02 (locale=en_CA.UTF-8,Utf16=on,HugeFiles=on,64 bits,2 CPUs Intel(R) Core(TM)2 Duo CPU     P9600  @ 2.53GHz (1067A),ASM)

Scanning the drive for archives:
1 file, 128 bytes (1 KiB)

Listing archive: Data/Folder2/Folder2.7z

--
Path = Data/Folder2/Folder2.7z
Type = 7z
Physical Size = 128
Headers Size = 128
Solid = -
Blocks = 0

   Date      Time    Attr         Size   Compressed  Name
------------------- ----- ------------ ------------  ------------------------
2018-02-12 18:37:37 ....A            0            0  file5
2018-02-12 18:37:37 ....A            0            0  file6
------------------- ----- ------------ ------------  ------------------------
2018-02-12 18:37:37                  0            0  2 files

注:!*/が履歴拡張演算子である環境(対話型bashシェルなど)では、!に追加のエスケープが必要になる場合があります。

3
steeldriver

これはテストされていないコードで、「echo」でのみ使用されます。複数のZipファイルで終わるのは嫌だからです。 7zaがわからないので、幻想的なZip構文ですが、説明します。

find . -type d -execdir /.../ad-hoc.sh {} ";"

スクリプトad-hoc.shは絶対パスでアドレス指定する必要があり、結果に影響しないように現在のパスにあるべきではありませんが、parentdirにある可能性があります。

find . -type d -execdir $PWD/../ad-hoc.sh {} ";"

そして、実行可能にされていない場合、明示的に呼び出されます:

find . -type d -execdir bash $PWD/../ad-hoc.sh {} ";"

Findは、タイプd(dirs)のファイルについてのみ、現在のディレクトリを検索します。ここで、パラメータ{}でbashscriptを実行し、見つかったディレクトリを探します。

わかりました-ad-hoc.shとは何ですか、dirとsubdirsで実行しますか?別の発見です:

#!/bin/bash
dir=$1
find $dir -maxdepth 1 -type f -exec echo Zip -o "$dir.Zip" {} +

-maxdepth 1は、サブディレクトリを検索するための検索を防ぎます。-typeは、ファイルを操作するだけです。 -execは「echo Zip ...」をテストするためのコマンドを起動しますが、有望に見える場合(バックアップを頻繁に行うので、そうではありませんか?)、あなたは-ここで、私の擬似コードを開始します:-o:= -output 「$ PWD.Zip」、および{} +はファイルリストです。

tree
.
├── buch-klein.kry
├── buch.kry
├── crypt
│   ├── moveto.sh.crypt
│   └── sub1
│       ├── foo.crypt
│       └── sub2
│           └── bar.crypt
├── original
│   ├── 1
│   │   └── 2
│   │       └── 3
│   ├── moveto.sh
│   └── sub1
│       └── sub2
│           └── up3 -> ../../../nr
├── outputfile.txt
├── rot.sh
└── zoom.sh

find . -type d -execdir $PWD/../ad-hoc.sh {} ";" 
Zip -o ./..Zip ././buch-klein.kry ././rot.sh ././buch.kry ././zoom.sh ././outputfile.txt
Zip -o ./original.Zip ./original/moveto.sh
Zip -o ./crypt.Zip ./crypt/moveto.sh.crypt
Zip -o ./sub1.Zip ./sub1/foo.crypt
Zip -o ./sub2.Zip ./sub2/bar.crypt

拡張子を持つすべてのファイルは通常のファイルであり、拡張子のないすべてのファイルはディレクトリまたはディレクトリへのシンボリックリンク(up3)です。

{}は、終了する「;」の前のfind -execコマンドの最後の要素でなければなりません。または+。したがって、それに応じて7zコマンドをビルドする必要があります。

あなたの7zaコマンドが

      7za a -t7z -r $dir.7za *

ad-hoc.shは次のようになります。

#!/bin/bash
dir=$1
find $dir -maxdepth 1 -type f -exec echo 7za -t7z -r "$dir.7za" {} +
0
user unknown