GNU/Linux >> Belajar Linux >  >> Linux

Mengapa `zip` Dalam A For Loop Bekerja Saat File Ada, Tapi Tidak Saat Tidak?

Saya memiliki direktori yang berisi beberapa sub-direktori. Ada pertanyaan tentang zip file yang berisi jawaban yang saya modifikasi sedikit untuk kebutuhan saya.

for i in */; do zip "zips/${i%/}.zip" "$i*.csv"; done

Namun, saya mengalami masalah yang aneh. Untuk kumpulan folder pertama, di mana zips/<name>.zip tidak ada, saya mendapatkan kesalahan ini:

zip error: Nothing to do! (zips/2014-10.zip)
        zip warning: name not matched: 2014-11/*.csv

namun ketika saya hanya echo pernyataan zip:

for i in */; do echo zip "zips/${i%/}.zip" "$i*.csv"; done

Kemudian jalankan perintah echoed (zip zips/2014-10.zip 2014-10/*.csv ), ini berfungsi dengan baik dan membuka ritsleting folder. Kemudian bagian yang menyenangkan tentang itu adalah menjalankan perintah asli berikutnya akan sebenarnya zip folder yang tidak berfungsi pertama kali!

Untuk menguji sendiri perilaku ini:

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

Anda akan melihat bahwa gema mencetak pernyataan berikut:

zip zips/2016-01.zip 2016-01/*.csv
zip zips/2016-02.zip 2016-02/*.csv
zip zips/2016-03.zip 2016-03/*.csv

Namun, perintah zip yang sebenarnya akan memberi tahu Anda:

        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%)

Jadi sebenarnya memperbarui file zip dengan .csv s tempat file zip ada, tetapi tidak saat file zip dibuat. Dan jika Anda menyalin salah satu perintah zip:

$ zip zips/2016-02.zip 2016-02/*.csv
adding: 2016-02/one.csv (stored 0%)
adding: 2016-02/two.csv (stored 0%)

Kemudian jalankan kembali zip-all-the-things:

for i in 2*/; do zip "zips/${i%/}.zip" "$i*.csv"; done

Anda akan melihatnya diperbarui untuk 2016-02 dan 2016-03 . Inilah hasil tree saya :

.
├── 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

Juga, (tidak) mengejutkan, ini berfungsi dengan baik:

zsh -c "$(for i in 2*/; do echo zip "zips/${i%/}.zip" "$i*.csv"; done)"

Apa yang saya lakukan salah di sini? (perhatikan, saya menggunakan zsh alih-alih bash, jika ada bedanya)

Jawaban yang Diterima:

Ekspansi oleh shell

Kutipan di sekitar "$i*.csv" membuat perbedaan. Dengan tanda kutip, shell memperluas string itu ke "2014-11/*.csv". File persis itu tidak ada, dan zip melaporkan kesalahan. Tanpa tanda kutip, * juga meluas (melalui ekspansi nama file/”globbing”), dan zip . yang dihasilkan perintah adalah daftar lengkap file yang cocok, masing-masing sebagai argumen terpisah. Anda bisa mendapatkan perilaku kedua, di dalam for lingkaran, dengan:

for i in */ ; do zip "zips/${i%/}.zip" "$i"*.csv ; done

Perluasan dengan zip

zip juga dapat memperluas wildcard untuk dirinya sendiri, tetapi tidak dalam semua situasi. Dari manual zip:

zip program dapat melakukan pencocokan yang sama pada nama yang ada di zip arsip sedang dimodifikasi atau, dalam kasus -x (kecualikan) atau -i (termasuk) opsi, pada daftar file yang akan dioperasikan, dengan menggunakan garis miring terbalik atau tanda kutip untuk memberi tahu shell agar tidak melakukan ekspansi nama.

Perintah asli berfungsi pada upaya berikutnya, setelah Anda berhasil membuat arsip, karena zip mencoba mencocokkan karakter pengganti dengan konten arsip yang ada. Mereka ada di sana, dan masih ada di sistem file, jadi mereka dilaporkan dengan updating: .

Untuk mendapatkan zip untuk menangani wildcard saat membuat arsip, gunakan -r (recurse) opsi untuk mengulang ke direktori yang diminta, dan -i (termasuk) untuk membatasinya pada file yang cocok dengan pola:

 for i in */ ; do zip -r "zips/${i%/}.zip" "$i" -i '*.csv' ; done

Linux
  1. Mengapa Ekspresi Reguler Bekerja Di X Tapi Tidak Di Y?

  2. Mengapa Substitusi Proses Bash Tidak Bekerja Dengan Beberapa Perintah?

  3. Mengapa Cara Berikut Tidak Mengubah Ukuran Batas File Inti?

  1. Mengapa File Terjemahan Bash Tidak Berisi Semua Teks Kesalahan?

  2. Linux – Mengapa Setuid Tidak Bekerja??

  3. Mengapa Ls -l Tidak Menunjukkan Waktu Dan Atau Tahun Untuk Setiap File??

  1. Mengapa Pelengkapan Otomatis Tidak Berfungsi Saat Mengetik Nama Perintah Setelah `sumber`?

  2. Linux – Mengapa Es_mx Lokal Bekerja Tapi Tidak Es?

  3. Mengapa `keluar &` Tidak Berfungsi?