いくつかのサブディレクトリを含むディレクトリがあります。 ファイルの圧縮に関する質問 があります。これには、ニーズに合わせて少し変更した回答が含まれています。
for i in */; do Zip "zips/${i%/}.Zip" "$i*.csv"; done
しかし、私は奇妙な問題に遭遇します。 zips/<name>.Zip
が存在しない最初のフォルダーのセットでは、次のエラーが発生します。
Zip error: Nothing to do! (zips/2014-10.Zip)
Zip warning: name not matched: 2014-11/*.csv
ただし、Zipステートメントをecho
するだけの場合:
for i in */; do echo Zip "zips/${i%/}.Zip" "$i*.csv"; done
次に、エコーされたコマンド(Zip zips/2014-10.Zip 2014-10/*.csv
)を実行すると、正常に機能し、フォルダーが圧縮されます。次に、それについての楽しい部分は、元のコマンドの後続の実行が実際には初めて機能しなかったフォルダを実際に圧縮することです。
この動作を自分でテストするには:
cd /tmp
mkdir -p 2016-01 2016-02 2016-03 zips
for i in 2*/; do touch "$i"/one.csv; done
for i in 2*/; do touch "$i"/two.csv; done
Zip zips/2016-03.Zip 2016-03/*.csv
for i in 2*/; do echo Zip "zips/${i%/}.Zip" "$i*.csv"; done
for i in 2*/; do Zip "zips/${i%/}.Zip" "$i*.csv"; done
エコーが次のステートメントを出力することがわかります。
Zip zips/2016-01.Zip 2016-01/*.csv
Zip zips/2016-02.Zip 2016-02/*.csv
Zip zips/2016-03.Zip 2016-03/*.csv
ただし、実際のZipコマンドは次のことを示します。
Zip warning: name not matched: 2016-01/*.csv
Zip error: Nothing to do! (zips/2016-01.Zip)
Zip warning: name not matched: 2016-02/*.csv
Zip error: Nothing to do! (zips/2016-02.Zip)
updating: 2016-03/one.csv (stored 0%)
updating: 2016-03/two.csv (stored 0%)
したがって、実際にはZipファイルが存在する.csv
sでZipファイルを更新していますが、Zipファイルの作成時にはnotではありません。また、Zipコマンドの1つをコピーした場合:
$ Zip zips/2016-02.Zip 2016-02/*.csv
adding: 2016-02/one.csv (stored 0%)
adding: 2016-02/two.csv (stored 0%)
次に、Zip-all-the-thingsを再実行します。
for i in 2*/; do Zip "zips/${i%/}.Zip" "$i*.csv"; done
2016-02
および2016-03
に対して更新されることがわかります。 tree
の出力は次のとおりです。
.
├── 2016-01
│ ├── one.csv
│ └── two.csv
├── 2016-02
│ ├── one.csv
│ └── two.csv
├── 2016-03
│ ├── one.csv
│ └── two.csv
└── zips
├── 2016-02.Zip
└── 2016-03.Zip
また、(不)意外にも、これは問題なく機能します。
zsh -c "$(for i in 2*/; do echo Zip "zips/${i%/}.Zip" "$i*.csv"; done)"
ここで何が悪いのですか? (違いがある場合は、bashの代わりにzshを使用していることに注意してください)
"$i*.csv"
を囲む引用符が違いを生み出します。引用符を使用して、シェルはその文字列を「2014-11/*。csv」に展開します。その正確なファイルは存在せず、Zip
はエラーを報告します。引用符がない場合、*
も展開され(ファイル名展開/ "globbing"を介して)、結果のZip
コマンドは、それぞれが個別の引数として一致するファイルの完全なリストになります。次のようにすると、for
ループ内で2番目の動作を取得できます。
for i in */ ; do Zip "zips/${i%/}.Zip" "$i"*.csv ; done
Zip
は、それ自体でワイルドカードを展開することもできますが、すべての状況で展開できるわけではありません。 Zipマニュアル から:
Zipプログラムは、変更中のZipアーカイブ内にある名前、または-x(除外)または-i(include)オプション、バックスラッシュまたは引用符を使用して、名前の展開を行わないようにシェルに指示することにより、操作するファイルのリスト。
Zip
はワイルドカードを既存のアーカイブの内容と照合しようとするため、アーカイブを正常に作成した後、元のコマンドは後続の試行で機能します。それらはそこに存在し、ファイルシステムにも存在するため、updating:
で報告されます。
アーカイブを作成するときにZip
にワイルドカードを処理させるには、-r
(recurse)オプションを使用して、要求されたディレクトリに再帰し、-i
(include)を使用して、パターンに一致するファイルに制限します。
for i in */ ; do Zip -r "zips/${i%/}.Zip" "$i" -i '*.csv' ; done