いくつかのサブディレクトリを含むディレクトリがあります。自分のニーズに合わせて少し変更した回答を含むファイルを圧縮することについて質問があります。
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
ただし echo
だけのとき zipステートメント:
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
で更新しています。 ■zipファイルは存在するが、は存在しない zipファイルが作成されたとき。また、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
エラーを報告します。引用符なしの場合、*
また、(ファイル名の展開/「グロブ」を介して)展開し、結果のzip
コマンドは、一致するファイルの完全なリストであり、それぞれが個別の引数として使用されます。 for
内で2番目の動作を取得できます ループ、with:
for i in */ ; do zip "zips/${i%/}.zip" "$i"*.csv ; done
zipによる拡張
zip
ワイルドカードをそれ自体で拡張することもできますが、すべての状況で拡張できるわけではありません。 zipマニュアルから:
zip プログラムは、 zipにある名前に対して同じマッチングを行うことができます 変更中のアーカイブ、または -xの場合 (除外)または -i (含む)操作するファイルのリストにあるオプション。バックスラッシュまたは引用符を使用して、名前の展開を行わないようにシェルに指示します。
zip
が原因で、アーカイブが正常に作成された後、元のコマンドは後続の試行で機能します ワイルドカードを既存のアーカイブの内容と照合しようとします。それらはそこに存在し、ファイルシステムにも存在するため、updating:
で報告されます 。
zip
を取得するには 作成時にワイルドカードを処理する アーカイブの場合は、-r
を使用します (recurse)要求されたディレクトリに再帰するオプション、および-i
(含む)パターンに一致するファイルに制限するには:
for i in */ ; do zip -r "zips/${i%/}.zip" "$i" -i '*.csv' ; done