Neden joker karakter * zip ve rm komutları arasında bu kadar farklı?


58

Benim için bazı işlemleri yapmak için bir senaryo hazırladım. *Bir türdeki tüm dosyalara işlev uygulamak için joker karakter operatörünü kullanıyorum , ancak anlamadığım bir şey var. unzipBöyle bir klasördeki tüm dosyaları yapabilirim

unzip "*".zip

Ancak, daha sonra tüm zip dosyalarını kaldırmak için yapmanız gereken

rm *.zip

Yani, tırnak işaretleri istemiyor. Diğer taraftan, unzip, sadece * verdiğimde çalışmaz (bana "dosyalar eşleşmedi" uyarısı verir).

Bu neden farklı? Bana göre bu aynı operasyon gibi görünüyor. Yoksa joker kartı yanlış mı kullanıyorum?

Yabani karta Tanıtımları Unix gerçekten bu işe gitmez, ben bir şey bulamadı rmveya zipdokümanlar.

Mac üzerindeki terminali kullanıyorum (Yosemite).


4
unzipNormal for f in *.zip;do...donekabuk döngüsü olmadan bunu yapabileceği hakkında hiçbir fikrim yoktu . Böyle garip bir unix benzeri olmayan komut satırı UI.
Peter Cordes

@Peter, durumu yanlış anladığınızı düşünüyorum. unzipglob'u bir arşivin içeriğine uygular; Bir joker ile bash onları alamazsınız. (F 'için `` gerekir unzip -l archive.zip;; bitti')
alexis

@alexis: unzipTek bir zip dosyası içinde eşleşmek üzere küre kabul etmeyi biliyordum . Ancak bu farklı; Aslında unzip '*.zip'birden fazla zip dosyasının bulunduğu bir dizinde denedim ve tüm dosyaları tüm fermuarlardan ayıklar. Dediğim gibi, süper garip. tarBöyle bir işlem modu yok.
Peter Cordes

1
@Peter görüyorum ... evet bu çok garip, çünkü unzip çoklu komut satırı argümanlarını kabul etmeyecek! Açıkça Windows sadece bir uygulama. OP'nin görev tanımını yanlış yorumladım.
alexis

1
@alexis: PKZip Windows önceden tarihler . Bu ilk olarak 1989'da yayımlanan bir DOS komut satırı programıdır. Unix bağlantı noktası temel olarak aynı cmdline ayrıştırma kodunu (AFAIK) kullanır.
Peter Cordes

Yanıtlar:


69

Durumu çok iyi açıkladın. Bulmacanın son parçası, unzipjoker karakterlerin kendisini idare edebilmesidir:

http://www.info-zip.org/mans/unzip.html

ARGÜMANLAR

dosya [Zip]

...

Joker karakter ifadeleri, yaygın olarak kullanılan Unix kabuklarında (sh, ksh, csh) desteklenenlere benzer ve şunları içerebilir:

*, 0 veya daha fazla karakter dizisiyle eşleşir

* Joker karakterini alıntılayarak, kabuğunuzun genişlemesini engellediniz, böylece unzipjoker karakteri görüyor ve kendi mantığına göre genişletmeyi ele alıyor.

rmaksine, joker karakterleri kendi başlarına desteklemez , bu nedenle bir joker karakter sunmaya çalışmak, rmbunun yerine dosya adında değişmez bir yıldız işareti aramayı söyler .

Neden unzip *.zipçalışmıyor olmasıdır unzips sözdizimi sadece birden fazla zip dosyasına izin vermiyor'; Birden fazla parametre varsa, 2. ve daha sonrakilerin arşivde dosya olmasını bekler:

unzip [-Z] [-cflptTuvz [abjnoqsCDKLMUVWX $ /: ^]] dosya [.zip] [dosya (lar) ...] [-x xfile ...] [-d exdir]


6
teşekkürler, bu mantıklı! eğer doğru anlarsam, bir durumda unzipkendi dilini konuşuyorum , diğer durumda genel unix lingo?
Patrick

6
Doğru. Bir programın yaptığına göre kabuğunuzun ne yaptığını unutmamak önemlidir.
Jeff Schaller

7
pkzip, DOS programlarında yayılan joker karakterleri genişletmeyen bir kaynak yarattı.
Thorbjørn Ravn Andersen

11
@patrick, aynı anda yalnızca bir dosya ile çalışabilen bir programla birden fazla dosyayı işlemenin unix yolunu bir döngü kullanmaktır. örn for f in *.zip ; do unzip -v "$f" ; done. ve NEDENİN kabuğun dosya adı genişlemesi vb. yapması nedeninin büyük bir kısmı, her bir programın gerekmediğidir (küçük fakat can sıkıcı yollarla birbirinden bağımsız olarak yazılmış birçok joker karakter eklemesi uygulaması ile sonuçlanacaktır). .
Cas

24

Bu iki komut arasındaki fark alıntı *karakterdir. Bir kabukta bir komut çağırıp *karakteri bir argüman için kullanırsanız , kabuğun kendisi argümanı değerlendirir. Bu örneğe bakın:

$ ls
file1.zip  file2.zip  file3.zip  file4.txt

Şimdi bir ile *:

$ ls *.zip
file1.zip  file2.zip  file3.zip

Kabuk joker karakterini değerlendirir ve aşağıdaki gibi bir komut oluşturur:

$ ls file1.zip  file2.zip  file3.zip

Alıntılanan bir joker karakterle (tam anlamıyla) adlı bir dosya olarak yorumlanır *.zip:

$ ls "*".zip
ls: cannot access *.zip: No such file or directory

Yardımcı unzipprogram, birden fazla sıkıştırılmış dosyayla bağımsız değişken olarak çağrılamaz. Ancak, geliştirici bunun için başka bir yol seçti. Manpage'den:

dosya [Zip]

[...] Joker karakter ifadeleri, yaygın olarak kullanılan Unix mermilerinde (sh, ksh, csh) desteklenenlerle aynıdır [...] ( Özellikle işletim sistemi tarafından başka şekilde yorumlanabilecek veya değiştirilebilecek herhangi bir karakter alıntı yaptığınızdan emin olun) Unix ve VMS.)


Yazarların neden unzipbirden fazla sıkıştırılmış dosya argümanlarına izin vermek yerine, o rotaya gitmeyi seçtiklerini biliyor musunuz ?
David Etler

@DavidEtler Ben de bilmiyorum.
kaos

1
Nedenini ya da @DavidEtler, ancak unzip unzip'in sözdizimini, bu zipfile'nin içeriği olarak kabul edilen zipfile'den sonra dosya adlarını kabul edemez diyemem. İkinci bir zip dosyasının bir "unzip me" parametresi mi, yoksa "bu dahili zip dosyasını bir önceki arşivden paketinden çıkarması" anlamına mı geldiğiniz belirsiz olurdu.
Jeff Schaller

@DavidEtler geliştiricilerin ne düşündüğünü bilmiyor, ancak o zamanlar her şey çok daha yavaş ve daha küçüktü. Genelde bir kerede birden fazla zip dosyasıyla ilgilenmiyordunuz. 90 veya 250kB tutan disketleriniz vardı ve 10 MB'lık bir disk sürücüsüne sahip olduğunuz için gerçekten mutluydunuz. İşler sıkıştırıldı, çünkü sadece sistemler arası taşımacılık için değillerdi.
Joe,

6

Aradaki fark, ilk durumda, kabuğun kendisi küreyi genişletir:

% cd /                                                       
% echo *
Applications Library Network System Users Volumes bin cores ...
% 

İkinci durumda, uygulamanın kendisi de bu gerçek karaktere sahip olan Something ™:

% cd /
% perl -E 'chdir "/tmp" or die; say for glob($ARGV[0])' "*"
com.apple.launchd.aj4FEhYqm5
...

İşaretlenmezse, kabuk önce dışa doğru genişler ve komut, o dışa doğru yayılanın ne olursa olsun çalıştırılır.


2

Bir komut argümanları kabuk tarafından işlendikten sonra alır.

İlk işlemede, *kabuk tarafından tırnak işaretleri arasında bir genişleme olacaktır (mevcut dizinde bulunan dosya listesine (pwd) göre).

echo *.zip

Tüm .zipdosyaları listeler . Ama echo "*".zip"olacak değil .

İlk işleme sırasında, bir alıntı "*"genişletilmeyecek, bir parametre olarak unzip komutuna verilecek (tırnak işaretlerinin kaldırılmasından sonra). Unzip komutu şu parametreleri alır *.zip:

$ echo unzip "*".zip
unzip *.zip

*Dosya listesini genişleten unzip komutudur .


Bu iki komutun da aynı son işlemi yapmaması ve *değişiklikleri kimin genişletmesi ilginçtir :

unzip "*".zip                ### the command unzip expands `*.zip`.
unzip *.zip                  ### the shell expands `*.zip`.

İlk komut *.ziptüm dosyaları işlemek için genişlediği bir komut alır . İkinci komut , unwip geliştiricisinin birden fazla dosyanın genişlemesini reddetmeyi seçtiğinden, işlem yapmadığı pwd'deki unziptüm .zipdosyaların bir listesini alır zip.


0

Zip, çoklu argümanları işleme biçimi nedeniyle, tırnak işaretleri gerekir:

rm: bağımsız değişken listesindeki tüm dosyaları kaldır

zip: ilk argümandaki dosyayı aç. sadece kalan değişkenlerdeki dosyaları çıkartın.

$ ls *.zip
file1.zip  file2.zip  file3.zip
$ unzip *.zip
Archive:  file1.zip
caution: filename not matched:  file2.zip
caution: filename not matched:  file3.zip

Gördüğünüz gibi, file2.zip ve file1.zip dosyasını file1.zip içinde bulmaya çalışır.

Aynı anda birden fazla zip dosyasını çıkarmanıza izin vermek için zip, küreyi farklı bir sonuçla kendi başına yorumlamayı destekler.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.