'Tar' komutunu 'find' ile nasıl birleştirirsiniz?


31

Find komutu bu çıktıyı verir:

[root @ localhost /] # var var / log / -iname anaconda. *
var / log / anaconda.log
var / log / anaconda.xlog
var / log / anaconda.yum.log
var / log / anaconda.syslog
var / log / anaconda.program.log
var / log / anaconda.storage.log

Tar ile birleştirdikten sonra bu çıktı gösteriliyor:

[root @ localhost /] # var var / log / -iname anaconda. * -exec tar -cvf file.tar {} \;
var / log / anaconda.log
var / log / anaconda.xlog
var / log / anaconda.yum.log
var / log / anaconda.syslog
var / log / anaconda.program.log
var / log / anaconda.storage.log

Ancak tar dosyasını listelerken sadece bir dosya gösteriliyor.

[root @ localhost /] # tar -tvf dosyası.tar
-rw ------- root / root 208454 2012-02-27 12:01 var / log / anaconda.storage.log

Neyi yanlış yapıyorum burada?

Xargs ile bu çıktıyı alıyorum:

[root @ localhost /] # bulmak var / log / -iname anaconda. * | xargs tar -cvf dosyası1.tar

İkinci soru

Var önünde / önünde yazarken , find /var/logneden bu mesaage tarını verdiğini belirtir : Başlıca `/ 'yi üye adlarından çıkarmak

[root @ localhost /] # find / var / log / -iname anaconda. * -exec tar -cvf file.tar {} \;
tar: Başlıca `/ 'yi üye adlarından çıkarma
/var/log/anaconda.log
tar: Başlıca `/ 'yi üye adlarından çıkarma
/var/log/anaconda.xlog
tar: Başlıca `/ 'yi üye adlarından çıkarma
/var/log/anaconda.yum.log
tar: Başlıca `/ 'yi üye adlarından çıkarma
/var/log/anaconda.syslog
tar: Başlıca `/ 'yi üye adlarından çıkarma
/var/log/anaconda.program.log
tar: Başlıca `/ 'yi üye adlarından çıkarma
/var/log/anaconda.storage.log

Basit bir biçimde, takip eden ikisi arasındaki fark nedir?

find var/log ve find /var/log


Bu yarı + kapalı konudur, ancak findkomutla ileri giderken , arama terimini alıntılamalısınız. Bazen olmadan çalışır ama her zaman değil.
nerdwaller

1
{} +Bunun yerine kullanırsanız {} \;buluntu sonuçlarını tek bir argüman olarak gruplandırırsınız
Jason S

Yanıtlar:


39

Not: Biraz daha verimli bir çözüm için @ Iain'in cevabına bakınız .

Not findarayacak -execeylemini her dosyanın bulduğu.

tar -cvf file.tar {}Her bir dosya findçıktısı için çalıştırırsanız , bu file.tarher seferinde üzerine yazacağınız anlamına gelir, bu da neden yalnızca içeren bir arşiv bıraktığını açıklar anaconda.storage.log- bu da en son findçıktılar.

Şimdi, aslında dosyaları her seferinde oluşturmak yerine arşive eklemek istiyorsunuz ( -cseçeneğin yaptığı budur). Yani, aşağıdakileri kullanın:

find var/log/ -iname "anaconda.*" -exec tar -rvf file.tar {} \;

Bu -rseçenek, her zaman yeniden oluşturmak yerine arşive eklenir.

Not: Değiştir -iname anaconda.*ile -iname "anaconda.*". Yıldız işareti bir jokerdir ve onu görmeden önce kabuğunuz tarafından genişletilebilirfind . Bu genişlemeyi önlemek için, argümanı çift tırnak içine alın.


tarÖnde gelenleri kaldırmaya gelince /: Arşiv yalnızca göreceli dosya adları içermelidir . Önde sahip dosyalar eklerseniz , örneğin bilgisayarınızda tam anlamıyla anlamına gelen mutlak dosya adları /olarak depolanırlar ./var/…

IIRC bu sadece tarGNU dışındaki uygulamalar için bir önlemdir ve bu şekilde daha güvenlidir, çünkü /var/…göreceli dosya adları içeriyorsa arşivi çıkarırken gerçek verilerinizin üzerine yazmazsınız .


6
Ancak tar, gerçek bir kaset arşivine bu şekilde girmeyi denerseniz, bir seferde bir dosya ekleyerek, kaseti geri sardıktan sonra her şeyi sonuna kadar yeniden okursanız, her şeyin saçma bir şekilde yavaş olacağını unutmayın. Çözümünüz sadece tar dosyasını diske yazıyorsanız uygundur.
Nicole Hamilton,

2
Doğru, ama sanırım bu durumu güvenle göz ardı edebiliriz;)
slhck

@slhck *, tüm olasılıklara uyması gereken bir joker karakter mi? ama burada find /var/log/ -iname anaconda*hiçbir şey find /var/log/ -iname anaconda.*vermeden ve çıktısını vererek, neden?
en fazla

Bir joker karakter tüketildiğinde, findartık görünmez. Öyleyse anaconda*, mevcut klasörünüzde, örneğin anaconda5(bu joker karakterle eşleştirme) adında bir şey varsa , joker karakter genişletilir ve bunun yerine findgörürsünüz . Neden birincisinin işe yaramadığı ve ikincisi ise mevcut dizininizde hangi dosyaların olduğuna bağlı. @max-iname anaconda5-iname anaconda*
slhck

2
Bunun {} +yerine kullanabilirsiniz , {} \;böylece
Jason S

41

Gibi bir şey kullanabilirsiniz:

find var/log -iname 'anaconda.*' -print0 | tar -cvf somefile.tar --null -T -

-print0Ve -Tbirlikte çalışma nihai vb alanlarda yenisatırlar ile dosya izin -stdin'den giriş dosya okumak için tar söyler.

Bu cevaba göre ifadenizin-print0 sonunda gelmesi gerektiğini unutmayın . Aksi takdirde, muhtemelen beklediğinizden daha fazla dosya alırsınız.


2
Bu -nameseçeneği atıp çözümünüzü tartüm dizine yönlendirdiniz. İstediğin buysa, tar -cvf file.tar var/loghiç kullanmadan olduğu gibi kolayca yapabilirsin find.
Nicole Hamilton,

2
+1 Listeyi boruya aktarmak tariyi bir fikirdir. Yol adlarının boşluk bırakabileceğini düşünüyorsanız, kesinlikle en iyi çözüm budur. Hem güvenilir hem de verimli olduğu için bunu en iyi teknik olarak bile tanımlarım. Ancak hem findve hem de ek özel bilgi gerektirir tar. Komut ikame yöntemini sadece çok daha genel bir araç olduğu için tercih ediyorum: Bir kere nasıl kullanılacağını öğren, sonra her yerde kullan. (Ama kabul ediyorum, Windows’ta her zaman çalıştığı bir kabuğum var.) Özür dilerim.
Nicole Hamilton,

2
+ 1'inizi zaten aldınız. Mutlu ol. :) Uzun komut satırları, her zaman herhangi bir işletim sisteminde işlem oluşturma i / f'sinin kısıtlamasıdır. Ben tartışmaya hatırlıyorum Mark Lucovsky onların 32K Unicode karakterler NT üzerinde sınırlamak o 90'lı yılların başlarında Microsoft'ta çok küçük ve ona sahip daha o çekirdekte her yerde boylam değerleri yerine şort olarak mağaza uzunlukları alacağını bayt kaç bilmiyordum şikayetçi . İç çekmek. Argü listesi çok uzun olduğunda, daha genel durum çözümleri kabuğunda daha fazlasını yapmak (mümkünse; benimkinde) veya kullanmaktır xargs.
Nicole Hamilton,

9
find'in seçeneğini kullanırsanız -print0, katran'ın --nullseçeneğine de ihtiyacınız vardır .
18

2
Ve --no-unquoteayrıca gerekli olduğu ortaya çıkıyor: ters eğik çizgi içeren dosya adları aksi takdirde yanlış işlenir. (Hayır, bu varsayımsal bir şey değil - Gerçekten başkasının kodundan bir tar arşiv oluşturuyorum, adında ters eğik çizgi bulunan bir dosya adı içeriyordum, bu şekilde öğrendim.)
hvd

12

Bunu dene:

tar -cvf file.tar `find var/log/ -iname "anaconda.*"`

Sen kullanmaya çalıştığınız findiçin -exec tar. Ancak -execseçeneğin çalışma şekli, bu komutu bulduğu her eşleşme dosyası için bir kez çalıştırır ve tarher seferinde ürettiği tar dosyasının üzerine yazılmasına neden olur . Bu yüzden sadece sonuncusu ile karşılaştın. Ayrıca, findkabuğun iletmeden önce genişlememesi için belirteceğiniz kalıbın etrafına tırnak koymanız gerekir find.

Geriye dönüş tuşlarıyla komut değiştirme özelliğini kullanarak (veya $(...)tercih ederseniz notasyonu kullanarak ), tarafından üretilen adların listesi findkomut satırına aynı taranda yazılmasına neden olacak şekilde argüman olarak yapıştırılır .


2
Adlarında, newlines veya globbing karakterlerinde boşluk içeren dosyaları bulursanız bu kötü sonuçlanabilir. Bu başarısızlığa bağlı - boru stdout'u findnadiren iyi bir fikir. mywiki.wooledge.org/ParsingLs
slhck

3
@slhck, piping stdout bulucu aslında yorumunuzda bağlantı verdiğiniz sayfada açıkça açıkça açıklandığı gibi genellikle iyi bir fikirdir :). Aslında bir şeyler yapmanın önerilen yolu budur. Sadece (gibi bazı hileler kullanmalıdır read -rarasında -print0benim cevap olduğu gibi).
Terdon

4
@slhck Unix ve Linux'taki dosya ve dizin adlarının geleneksel olarak adlardaki boşluklardan kaçınmasının nedeni budur. Ayrıca, boşluk içeren adların yaygın olduğu Windows'da, tüm satırları (muhtemelen boşluklar da dahil olmak üzere) komutun üzerine geri yapıştırılacak tek bir sözcük olarak işleyen çift geri döndürme çubukları kullanarak kendi Hamilton C kabuğuma ek bir komut değiştirme notasyonu ekledim. hat. Maalesef, Unix kabukları hiçbiri bu özelliğe sahip değil.
Nicole Hamilton,

1
Geleneksel olarak bundan kaçınıyor olabilirler, ancak kullanıcı alanında GUI'ler aracılığıyla oluşturulan dosyalar sayesinde, artık dosyaları olan boşlukları ihmal edemez ve dosyalara ikinci sınıf vatandaş olarak bakamazsınız (çünkü bu Unix'tir). Kabuğuna eklemen çok hoş, ama Windows için, ve eğer doğru sözdizimini kullanıyorsan ve uygun önlemleri alırsan , Unix kabukları bu özelliğe ihtiyaç duymaz . Bu yüzden ilk başta yorumumu gönderdim.
slhck

2
Hayır, ama başka yerlerde de çok iyi olabilir. Bu yüzden defansif program yapmak iyi bir fikir - özür dilemekten daha iyi güvende olmak. Ayrıca, bu soruyu bulan ziyaretçiler mutlaka aynı soruna sahip olmayabilir ve burada buldukları komutun neden bu durumda işe yaradığını ama onlar için başarısız olduğunu merak ediyor olabilirler. Komutu düzeltmek için size bırakacağım, bunu söylemenin önemli olduğunu düşündüm, çünkü çoğu kişi bu konuya er ya da geç rastlar.
slhck

6

Soru 1

Komutunuz başarısız çünkü tarher bir dosya bulundu ve bunları arşivliyor file.tar. Bunu her yaptığında, önceden oluşturulmuş olanın üzerine yazacaktır file.tar.

İstediğiniz şey tüm dosyalar için tek bir arşiv ise, tardoğrudan doğrudan çalıştırın , buna gerek yoktur find(ve evet, adlarında boşluk olan dosyalar için işe yarar):

tar -vcf file.tar /var/log/anaconda*   

soru 2

İki komut tamamen farklı:

  • var / log bul var/log , geçerli dizininizin bir alt dizini olan bir dizini arayacaktır , buna eşdeğerdir find ./var/log(dikkat edin ./).

  • find / var / log /var/log kökün alt/ dizini olan bir dizinde arama yapacaktır .

Baştaki /mesaj tardeğil find. Bu , göreli olarak mutlak yollar /oluşturmak için dosya adlarınızın ilkini kaldırıyor demektir . Bu , arşivi kaldırdığınızda dosyadaki dosyanın çıkarılacağı anlamına gelir ./var/log/anaconda.error./var/log/anaconda.error


1

-execÇalışmanın iki yolu var . Tek yön komutu birçok kez çalıştırır - her dosya için bir kez; diğer yol ise, tüm dosyalar için parametre listesi de dahil olmak üzere komutu bir kez çalıştırır.

  • -exec tar -cvf file.tar {} ';'tarher dosya için komutu çalıştırır, her seferinde arşivin üzerine yazar.
  • -exec tar -cvf file.tar {} '+'tarkomutu bir kez çalıştırır, bulunan tüm dosyaların arşivini oluşturur.

1

Her dosya için -exec kullanmak, çok fazla dosyanız varsa, tar sıkıştırmasını çok yavaşlatabilir. Komutu kullanmayı tercih ederim:

find . -iname "*.jpg" | cpio -ov -H tar -F jpgs.tar

başarısızlıkla başlayana kadar/bin/cpio: xxx: Cannot open: Too many open files
SYN
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.