Tüm dosyaları görüntülemek için find komutuna cat tarafından döndürülen dosyaların listesi nasıl borulanır


204

Ben yapıyorum findve sonra dosyaların bir listesini almak. Nasıl cat(cat tüm bu dosyaların içeriğini görüntüler) gibi başka bir yardımcı programa nasıl boru ve temelde grepbu dosyalardan bir şey gerekir .

Yanıtlar:


340
  1. Başka bir sürece borulama (Bu, yapmaya çalıştığınızı söylediklerinizi yerine getirmeyecek olsa da):

    command1 | command2
    

    Bu, command1 çıktısını command2 girişi olarak gönderir

  2. -execüzerinde find(bu, yapmak istediğiniz şeyi yapacak - ancak spesifik olan find)

    find . -name '*.foo' -exec cat {} \;
    

    (Her şey arasında findve -execzaten kullandığınız bulmak yüklemleri vardır. {}Eğer komuta içine bulundu belirli dosya (yerine yerleştirir cat {}bu durumda); \;bitmesini olan -execkomutu.)

  3. bir işlemin çıktısını başka bir işleme komut satırı bağımsız değişkenleri olarak gönderme

    command2 `command1`
    

    Örneğin:

    cat `find . -name '*.foo' -print`
    

    (Bu GERİ-KEŞİF benim klavyede tildeli ~ altında düzenli tırnak () olduğunu unutmayın.) Bu çıktısını gönderir command1içine command2komut satırı bağımsız değişkenleri olarak. Yine de boşluk içeren dosya adlarının (satırsonu vb.) Ayrı bağımsız değişkenlere bölüneceğini unutmayın.


2
kedi find -name '*.foo' -printbenim için harika çalıştı ... Teşekkürler
Devang Kamdar

Geri tırnaklar harika çalışır ve daha genelleştirilmiştir, bunu bir dosyadaki dosyaların listesini de oluşturmak için kullanabilirsiniz.
Hazok

11
Modern sürümlerinin şunu findyazmanıza izin verdiğini unutmayın : find . -name '*.foo' -exec cat {} +Burada, tek bir komut çağrısında uygun sayıda dosya adını gruplaması gerektiğini +belirtir find. Bu oldukça kullanışlıdır (dosya adlarında boşluklar vb. İle başvurmadan ilgilenir -print0ve xargs -0).
Jonathan Leffler

18
Sözü edilmemiş:find . -name '*.foo' | xargs cat
stewSquared

3
Sadece @stewSquared s cevabına eklemek için: Belli bir dize içeren dosyalardaki tüm satırları bulmak için, yapınfind . -name '*.foo' | xargs cat | grep string
Bim

84

Modern versiyon

POSIX 2008, +işaretleyiciyi ekledi; findbu, artık makul olduğu kadar çok dosyayı tek bir komut yürütmesinde otomatik olarak gruplandırdığı anlamına geliyor, tıpkı xargsbir çok avantajla:

  1. Dosya adlarındaki tek karakterler için endişelenmenize gerek yok.
  2. Komutun sıfır dosya adıyla çağrılması konusunda endişelenmenize gerek yoktur.

Dosya adı sorunu ile ilgili bir sorun olduğunu xargsolmadan -0seçeneği ve konuya 'hatta sıfır dosya adları ile çalıştırmak' olan veya olmayan bir sorun olduğunu -0seçenek - ama GNU xargsvardır -rya --no-run-if-emptyonun için ona karşı seçeneğine. Ayrıca, bu gösterim, performans farkını ölçmeniz muhtemel değil, süreç sayısını azaltır. Bu nedenle, mantıklı olarak şunları yazabilirsiniz:

find . -exec grep something {} +

Klasik versiyon

find . -print | xargs grep something

Linux üzerinde konum veya GNU varsa findve xargskomutları, daha sonra kullanmak -print0ile findve -0ile xargsboşluk ve diğer garip top karakter içeren tanıtıcı dosya adlarına.

find . -print0 | xargs -0 grep something

Sonuçların değiştirilmesi grep

Dosya adlarını (yalnızca metin) istemiyorsanız, uygun bir seçenek ekleyin grep(genellikle -h'başlıkları' bastırmak için). Kesinlikle dosya adı ile yazdırılır garanti etmek için grep(sadece bir dosya bulunursa veya son çağırma bile grepsadece 1 dosya adı verilir), sonra eklemek /dev/nulliçin xargsdaima en az iki dosya adları olacak böylece, komut satırından.


Benim gibi kafası karışmış olanlar için, bu yolun önce tüm bulgunun çıktısını vereceğini ve sonra da çıktısını vereceğini unutmayın xargs grep something.
Eric Hu

3
@EricHu: Kafanızın karıştığını görebiliyorum, ama söylediklerini yapmıyor, en azından bildiğim herhangi bir Unix tabanlı sistemde değil. Çıkışı findstandart girişine eklenir xargs. xargsProgram boşluk en (boşluk, yeni satır sekme, vs) girişi bölme, standart okur ve komuta sözcük sayısını ekler grep somethingve komut hattı yürütür. xargsdaha sonra giriş okumaya ve giriş bitene kadar komutları yürütmeye devam eder. komutu verilen girdi için gerektiği sıklıkta xargsçalıştırır grep( findbu örnekte).
Jonathan Leffler

Ah benim hatam, bu eşleşen her dosya içinde arama için grep kullanıyor. Ben sadece grep ile bulmak çıktı filtre arıyordum
Eric Hu

1
Hatalar, iyi davranan tüm komutlarda standart hataya (dosya tanımlayıcı 2) gider. /dev/nullHata mesajlarını kaybetmek için stderr yönlendiriliyor .
Jonathan Leffler

1
Bu, dosya yolundaki boşluklarla daha iyi çalışması avantajına da sahiptir. Hatta 'sed'ing "" -> "\" bile `` ile kırıyor ama xargs ile mükemmel çalışıyor
JZL003

36

Teknik olarak hepsi piping kullanmasa da find, catkomut tarafından döndürülen dosyaların listesini komuta iletmenin birkaç yolu vardır ve hiçbiri doğrudan doğrudan boru oluşturmaz cat.

  1. En basiti backticks ( `) kullanmaktır :

    cat `find [whatever]`
    

    Bu, çıktısını alır findve etkin bir şekilde komut satırına yerleştirir cat. findÇok fazla çıktı (bir komut satırına sığabileceğinden daha fazla) veya çıktıda özel karakterler (boşluklar gibi) varsa bu işe yaramaz .

  2. Aşağıdakiler de dahil olmak üzere bazı kabuklarda, ters çentikler yerine bashkullanılabilir $():

    cat $(find [whatever])
    

    Bu daha az taşınabilir, ancak tartışılabilir. Bunun yanı sıra, geri tepmelerle hemen hemen aynı uyarılara sahiptir.

  3. Bulunan şeyde başka komutlar çalıştırmak yaygın bir kullanım olduğundan find, find, -execbulduğu her dosya için bir komut yürüten bir eyleme sahiptir:

    find [whatever] -exec cat {} \;
    

    {}Dosya için bir yer tutucudur ve \;komuta uç işaretleri (Mümkün sonra diğer işlemler olur -exec.)

    Bu, verimsiz olabilen ve bazı komutlar için istediğiniz davranışlara sahip olmayabilecek birden fazla dosya adını geçirmenin cattek bir örneğini çalıştırmak yerine her bir dosya için bir kez çalışır cat(iyi olsa da cat). Sözdizimi de yazmak için gariptir - noktalı virgülten kaçmanız gerekir çünkü noktalı virgül kabuğa özeldir!

  4. Bazı sürümleri find(özellikle GNU sürümü) ;, +aşağıdakilerin -execdaha az örneğini çalıştırmak için 'ekleme' modunu kullanmanıza izin verir cat:

    find [whatever] -exec cat {} +
    

    Bu, her çağrı için birden fazla dosya adı geçirecektir cat, bu da daha verimli olabilir.

    Ancak bunun tek bir çağrı kullanacağının garanti edilmediğini unutmayın . Komut satırı çok uzun olursa, argümanlar birden çok çağrısına yayılır cat. İçin catbu muhtemelen büyük bir anlaşma değil, ama diğer bazı komutlar için bu istenmeyen şekilde davranışını değiştirebilir. Linux sistemlerinde, komut satırı uzunluk sınırı oldukça büyüktür, bu nedenle birden fazla çağrmaya bölünmek diğer bazı işletim sistemlerine kıyasla oldukça nadirdir.

  5. Klasik / taşınabilir yaklaşım xargsşunları kullanmaktır :

    find [whatever] | xargs cat
    

    xargsbelirtilen komutu çalıştırır ( catbu örnekte) ve stdin'den okuduklarına göre argümanlar ekler. Gibi sadece -execile +gerekirse bu komut satırı yukarı kıracak. Yani, findçok fazla çıktı üretirse, catbirden çok kez çalışır. Daha -execönceki bölümde bahsedildiği gibi, bu bölünmenin farklı davranışlara yol açabileceği bazı komutlar vardır. Bunun xargsgibi xargskullanmanın, boşlukları sınırlayıcı olarak kullandığından dosya adlarındaki boşluklarla ilgili sorunları olduğunu unutmayın .

  6. En sağlam, taşınabilir ve verimli yöntem ayrıca xargsşunları kullanır :

    find [whatever] -print0 | xargs -0 cat
    

    -print0Bayrak söyler findkullanmak \0dosya adları arasında (null karakteri) ayraçları ve -0bayrak söyler xargsbunlar beklemek \0ayraçları. Bu, -exec... +yaklaşımla hemen hemen aynıdır , ancak daha taşınabilir (ama ne yazık ki daha ayrıntılı).


Backtick yöntemi harika, çünkü aynı zamanda diğer komutlar için de çalışıyor ls.
Martin Braun

@Martin Braun kullanarak $()Ayrıca dışındaki komutlarla da çalışır find .
Laurence Gonsalves

Teşekkürler, bilmek güzel, (1) 'den sonra okumayı bıraktım çünkü boşlukları ve benzeri özel karakterlerle uğraşmadığım için ihtiyaçlarımı karşılıyor.
Martin Braun

9

Bunu elde etmek için (bash kullanarak) aşağıdakileri yaparım:

cat $(find . -name '*.foo')

Bu, "komut ikamesi" olarak bilinir ve varsayılan olarak gerçekten rahat olan satır beslemesini keser!

burada daha fazla bilgi


6

Bana bir kabuk senaryosu için bir iş gibi geliyor:

for file in 'find -name *.xml'
do
   grep 'hello' file
done

ya da böyle bir şey


2
Bu, her zaman zorunlu olmamakla birlikte, soru için geçerli bir cevaptır.
Jonathan Leffler

1
... evet, ancak dosya adlarının listelendiği büyük bir dosya istiyorsanız harikadır.
ʍǝɥʇɐɯ

1
Bunu en çok sevdim. Bunun gibi bir döngü bloğu başka şeyler yapmak için yer bırakır.
kakyo

4

İlgilendiğim bazı içerikler içeren dosya adlarını bulmanın yolu: Dosya adlarındaki boşlukları da güzel işleyen tek bir bash satırı:

find . -name \*.xml | while read i; do grep '<?xml' "$i" >/dev/null; [ $? == 0 ] && echo $i; done

3

Böyle bir şey kullanıyorum:

find . -name <filename> -print0 | xargs -0 cat | grep <word2search4>

" -print0find" için " -0" argümanı ve "xargs" için "argümanı, dosya yollarındaki / adlardaki boşlukları doğru işlemek için gereklidir.



2

İşte genel kullanım için çekimim:

grep YOURSTRING `find .`

Dosya adını yazdıracak


2

Bash'da aşağıdakiler uygun olacaktır:

find /dir -type f -print0 | xargs -0i cat {} | grep whatever

Bu, /dirdizindeki tüm dosyaları bulur ve güvenli bir şekilde xargssürecek dosya adlarını güvenli bir şekilde aktarır grep.

xargsBinlerce dosyanız varsa atlamak iyi bir fikir değildir /dir; cataşırı değişken listesi uzunluğu nedeniyle kırılacaktır. xargsher şeyi sizin için halledecek.

-print0Argüman findile mesh -0argüman için xargsdüzgün boşluklu dosya isimlerinin işlenmesinde. To -iargümanı xargs, catkomut satırında gereken yere dosya adını eklemenizi sağlar . Köşeli parantezlerin yerine catkomuttan geçirilen dosya adı kullanılır find.


0

Bu benim için çalışıyor

find _CACHE_* | while read line; do
    cat "$line" | grep "something"
done

0

Ggrep kullanın .

ggrep -H -R -I "mysearchstring" *

geçerli dizinde veya alt dizinde bulunan metin içeren unix'te bir dosyayı aramak için


0

Bu, yalnızca dosyaların adını ve içeriğini yinelemeli olarak yazdırır.

find . -type f -printf '\n\n%p:\n' -exec cat {} \;

Düzenle (Geliştirilmiş sürüm): Bu, yalnızca metin (ascii) dosyalarının adını ve içeriğini yinelemeli olarak yazdırır.

find . -type f -exec grep -Iq . {} \; -print | xargs awk 'FNR==1{print FILENAME ":" $0; }'

Bir deneme daha

find . -type f -exec grep -Iq . {} \; -printf "\n%p:" -exec cat {} \;

-1

Dosyalarda metin bulmaya mı çalışıyorsunuz? Bunun için grep'i kullanabilirsiniz ...

grep searchterm *

-1

/ Ghi ve / jkl dizinlerindeki bir sunucudaki tüm abc.def dosyalarının içeriğini listelemek ve görmek için

find /ghi /jkl -type f -name abc.def 2> /dev/null -exec ls {} \; -exec cat {} \;

Girişleri yorumlayan ve görüntüleyen abc.def dosyalarını listelemek için / ghi ve / jkl dizinlerindeki bu girişlere bakın.

find /ghi /jkl -type f -name abc.def 2> /dev/null -exec grep -H ^# {} \;
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.