listeden grep dosyaları


14

Birkaç yüz dosya listesini karşı grep çalıştırmak çalışıyorum:

$ head -n 3 <(cat files.txt)
admin.php
ajax/accept.php
ajax/add_note.php

Ancak, dosyalarda bulunduğunu bildiğim bir dize için selamlıyorum bile, aşağıdaki dosyaları aramaz:

$ grep -i 'foo' <(cat files.txt)

$ grep -i 'foo' admin.php
The foo was found

Bir dosyadaki kalıpları-f okuyan bayrağa aşinayım . Ancak girdi dosyaları nasıl okunur ?

Biçimi cpdesteklediği gibi geçici bir dizine dosyaları kopyalama <(cat files.txt)ve oradan dosyaları selamlama korkunç bir çözüm düşünmüştü. Shirley daha iyi bir yol var.

Yanıtlar:


22

Dosyaların listesini değil dosya adlarının listesini açıyor gibi görünüyorsunuz. <(cat files.txt)sadece dosyaları listeler. <(cat $(cat files.txt))Bunları gerçekten birleştirmeye ve tek bir akış olarak aramaya çalışın veya

grep -i 'foo' $(cat files.txt)

tüm dosyaları grep vermek.

Ancak, listede çok fazla dosya varsa, bağımsız değişken sayısı ile ilgili sorunlarınız olabilir. Bu durumda sadece yazardım

while read filename; do grep -Hi 'foo' "$filename"; done < files.txt

Teşekkür ederim! Bunun gibi whilefile.txt satırlarını alabileceğini fark etmedi .
dotancohen

Bu split + glob operatörünün glob bölümünü burada devre dışı bırakmak isteyeceksiniz (kabuk zsh değilse).
Stéphane Chazelas

1
whiledosyadan satırları tam olarak almıyorsa read, bunu yapıyor; whilesadece bunu bir döngü içinde yapmamıza izin verin. Döngü readbaşarısız olduğunda (yani, sıfır olmayan bir dönüş kodu döndürür), normalde Dosya Sonuna ulaşıldığından dolayı sona erer .
PM 2Ring

1
Bir (metin) satırını okumak için, sözdizimi IFS= read -r filename, read filenamebaşka bir şeydir.
Stéphane Chazelas

1
Bunun -Hbir GNU uzantısı olduğunu unutmayın . Biraz eksik --.
Stéphane Chazelas

8
xargs grep -i -- foo /dev/null < files.txt

dosyaların boş veya yeni satırla sınırlandırıldığı varsayılarak (bu ayırıcılardan kaçmak için tırnak işaretleri veya ters eğik çizgiler kullanılabilir). GNU ile xargssınırlayıcıyı belirtebilirsiniz -d(daha sonra tırnak işlemeyi devre dışı bırakır).

(unset -v IFS; set -f; grep -i -- foo $(cat files.txt))

dosyaların boşluk, sekme veya satırsonu ayrılmış olduğunu varsayarsak (bunlara atayarak farklı bir ayırıcı seçebilmenize rağmen bunlardan kaçmanın yolu yoktur IFS). Dosya listesi çoğu sistemde çok büyükse bu başarısız olur.

Bunlar ayrıca hiçbir dosyanın çağrılmadığını varsayar -.


En azından ve $(< file)yerine kullanmak daha iyi / daha hızlıdır . $(cat file)bashzsh
jimmij

7

Stdin dosya adlarının bir listesini okumak için kullanabilirsiniz xargs. Örneğin,

cat files.txt | xargs -d'\n' grep -i -- 'foo'

Varsayılan olarak, xargsstandart girdiden boşluklarla ayrılmış öğeleri okur. -d'\n'O boşlukları içeren dosya adlarını işleyebilir böylece, argüman sınırlayıcı olarak yeni satır kullanmak söyler. (Stéphane Chazelas'ın belirttiği gibi, bu bir GNU uzantısıdır). Ancak, yeni satırlar içeren dosya adlarıyla başa çıkmaz; bunlarla başa çıkmak için biraz daha karmaşık bir yaklaşıma ihtiyacımız var.

FWIW, bash'ın komutu çok yavaş olduğundan, bu yaklaşım bir while readdöngüden biraz daha hızlıdır read- veri karakterini karaktere göre xargsokurken, girdisini daha verimli bir şekilde okur. Ayrıca, komutu xargsyalnızca gerektiği kadar çağırır, grepher çağırma birden fazla dosya adı alır ve bu grepher dosya adı için ayrı ayrı çağırmaktan daha etkilidir .

Daha fazla ayrıntı için xargs man sayfasına ve xargs bilgi sayfasına bakın.


3

xargsfiles.txtseçeneği ile bir dosyadan ( listeniz gibi ) öğeleri okuyabilir :

   --arg-file=file
   -a file
          Read items from file instead of standard input.  If you use this
          option, stdin remains unchanged when commands are  run.   Other
          wise, stdin is redirected from /dev/null.

Yani bu da işe yaramalı:

xargs -a files.txt grep -i 'foo'

veya dosya adlarındaki boşluklar için

xargs -d'\n' -a files.txt grep -i 'foo'
xargs -I{} -a files.txt grep -i 'foo' {}

1

Bir for da yapabilirsiniz, ancak Orion örneği en basit olanıdır:

for i in $(cat files.txt); do grep -i 'foo' $i ; done

(Files.txt dosyasında listelenen her dosya için grep komutunu yürütün.)

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.