GNU/Linux >> Linux の 問題 >  >> Linux

ファイルが存在する場合にforループの`zip`が機能するのに、存在しない場合は機能しないのはなぜですか?

いくつかのサブディレクトリを含むディレクトリがあります。自分のニーズに合わせて少し変更した回答を含むファイルを圧縮することについて質問があります。

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

Linux
  1. Bashスクリプトがエイリアスを認識しないのはなぜですか?

  2. 〜/ .bash_profileが機能しないのはなぜですか?

  3. 一部のコマンドでBashプロセス置換が機能しないのはなぜですか?

  1. 正規表現がXで機能するのに、Yでは機能しないのはなぜですか?

  2. 次の方法でコアファイルの制限サイズが変更されないのはなぜですか?

  3. ヒアドキュメントの親シェルがダッシュのサブコマンドでは機能しないのに、Bashは機能するのはなぜですか?

  1. コマンドShufファイル>ファイルは空のファイルを残しますが、同様のコマンドは残しませんか?

  2. Bash翻訳ファイルにすべてのエラーテキストが含まれていないのはなぜですか?

  3. Linux –Setuidが機能しないのはなぜですか??