Adında özel karakter içeren dosyalarda find ve tar komutunu kullanma


5

Bir klasördeki tüm .ctl dosyalarını tekrar tekrar arşivlemek istiyorum.

tar -cf ctlfiles.tar `find /home/db -name "*.ctl" -print`

Hata mesajı:

tar: Removing leading `/' from member names
tar: /home/db/dunn/j: Cannot stat: No such file or directory
tar: 74.ctl: Cannot stat: No such file or directory

Bu dosyalar var: / home / db / dunn / j 74.ctl ve j 75. Fazladan alana dikkat edin. Dosyaların başka özel karakterleri varsa? Bu dosyaları tekrarlamalı olarak nasıl arşivlerim?

Yanıtlar:


5

-TBaşka bir dosyadaki dosyaların listesini okumasını söylemek için tar özelliğini kullanın (tar, her satırı ayrı bir dosya olarak kabul eder).

Ardından <(), kabuğunuzun bir komutun çıktısından sözde bir dosya oluşturmasını sağlamak için gösterimi kullanabilirsiniz :

tar cf ctlfiles.tar -T <(find /home/db -name "*.ctl")

Kabuğunuzun <()notasyonu desteklememesi durumunda geçici bir dosya kullanabilirsiniz:

find /home/db -name "*.ctl" > ctlfile-list
tar cf ctlfiles.tar -T ctlfile-list
rm ctlfile-list

Bir dosya adı yeni bir satır içeriyorsa, bu başarısız olur. Nadir ama mümkün.

@davisre - iyi nokta
R Samuel Klatchko

bu doğru cevap, bir katran örneğine içeriği stdin'den almak için gereken dosya adlarını okumalarını söyler. @ davisre: zsh içinde ctrl-v-enter ile bir dosya adı oluşturmaya çalıştım, bu bir yaratıyor ve bu çözüm hala çalışıyor. belki bir \ n ile işe yaramaz ama bence bu tür dosya adlarına sahip olmak oldukça nadirdir, dosya adlarında unicode karakterlere sahip olmak daha olasıdır.
akira

Newline problemini düzeltebilirsin --null; bkz David Bartlett cevabı . (Bu ayrıca, UTF-8 veya ISO-8859- x gibi genişletilmiş bir ASCII kodlaması kullandıkları sürece rastgele Unicode karakterleriyle de çalışır .)
wchargin

4

Aşağıdaki gibi -print0 özelliğini, xargs'ın -0 özelliği ile kullanabilirsiniz:

find /home/db -name '*.ctl' -print0 | xargs -0 tar -cf ctlfiles.tar

-print0 (bu, kısa çizgi-sıfır-sıfır), boşluklar yerine yollar arasında sınırlayıcı olarak boş değer bulmayı, -0 (sıfır, sıfır) aynı şekilde beklemelerini söyler.

Eklemek için düzenlendi:

Çok sayıda dosyanız varsa, xargs bir kereden fazla tar çalıştırabilir. Bununla başa çıkma yolları için yorumları görün veya doğrudan tar çağırmayı bulun, bu şekilde, adlarında boşluk veya satırsonları olsa bile, istediğiniz sayıda dosyayla çalışır:

rm -f ctlfiles.tar
find /home/db -name '*.ctl' -exec tar -rf ctlfiles.tar {} +

xargsÇok fazla argüman olduğuna karar verirse komutu birden çok kez çalıştırmak istediğinde başarısız olur .
R Samuel Klatchko

Doğru, ama -r seçeneğini tar'a eklemenin bunu düzeltmesi gerektiğine inanıyorum.

Aslında, -r kullanırsanız, muhtemelen xargs ile başa çıkabilirsiniz ve doğrudan tar çağırmayı bulabilirsiniz, şunun gibi: find / home / db -name '* .ctl' -exec tar -rf ctlfiles.tar {} \; Her ne kadar pratikte, orijinal cevap muhtemelen işe yarayacaktı - eğer dosya sayısı binlerce değilse - ve N kere yerine bir kez tar çağırdı.

Rakamı ayrıca xargs -0 -n 1000000000000ve ardından bir trilyon eşyadan daha azına sahip olduğunuz sürece ayarlayabilirsiniz.
Sophie Alpert

cevabın ilk kısmı işe yaramıyor çünkü "isimleri" tar olarak içeriyor, "tarın tarball'a koymak zorunda olduğu dosya isimleri" değil. Bulunan her dosya için (2. bölümde önerildiği gibi), xargs olayı ve tar işlenmesi gereksizdir.
akira

2

"-T" yi izleyen argüman "-" olduğunda, dosyaların listesi stdin'den alınır. Tar'ın son sürümleri tipik olarak, "-T" seçeneği tarafından belirtilen kaynakta verilen dosyaların null ayrılmış olduğunu gösteren "-null" seçeneğini destekler.

Dolayısıyla, aşağıdakiler, muhtemelen yeni satır karakterleri içeren, rastgele sayıda dosyayla çalışır:

find /home/db -name '*.ctl' -print0 | tar --null -T - -cf ctlfiles.tar

+ 1; bu tek güvenli ve taşınabilir cevaptır.
wchargin
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.