Konum bulma aramasında dizinleri hariç tutma


14

İle yapılan bir arama locatedosya sisteminde bulur yolları.
Genellikle, yalnızca dosyalarla veya yalnızca dizinlerle ilgilendiğiniz bir önsezi bilirsiniz.
Bir 'bulma' araması genellikle birçok sonuç döndürür. Çıktıyı kısaltmaya yardımcı olduğu için sonuca yalnızca türlerden birini dahil etmek yararlı olacaktır.

Ancak dosya veya dizinleri dışarıda bırakmak için daha ilginç bir argüman vardır: çünkü sonuç yollarının listesi belirsiz olabilir - sadece teoride değil.

Aşağıdaki örnek, sıradışı olmayan gerçek bir dünya örneğidir:

$ locate --regex --basename "xfce4-keyboard-overlay$"
/usr/local/bin/xfce4-keyboard-overlay
/usr/local/share/xfce4-keyboard-overlay

Tamam, bir şey bulduk! Ama ... dosyalar veya dizinler?

$ file /usr/local/bin/xfce4-keyboard-overlay 
/usr/local/bin/xfce4-keyboard-overlay:   bash script

Bu bir dosya ...

$ file /usr/local/share/xfce4-keyboard-overlay
/usr/local/share/xfce4-keyboard-overlay: directory

ikinci değil.

Bu belirsizlik, uzun yol listelerinin okunmasını zorlaştırıyor, bu nedenle dizinleri filtrelemek gerçekten güzel olurdu, örneğin için bir comman line seçeneği kullanarak locate.

Böyle bir şey var mı? Dizinler için filtre konumdan ayrı olsa bile?

En azından, kontrol edilecek tüm dosya adlarını yinelemek için bir komut dosyası kullanılabilir - bu yavaş olabilir.

Yanıtlar:


3

İle zsh:

print -rl ${(0)^"$(locate -0 ...)"}(N.)

(0)locate -0kısaca NUL karakterlerine (kullandığımız gibi ) bölen bir parametre genişletme işaretidir (ps:\0:).

İle ^, (N.)dizinin sonuna eklemek yerine, her öğeye ekleriz.

(N.).yalnızca normal dosyaları eşleştirmek N, öğeyi eşleşmiyorsa (yoksa veya normal bir dosya değilse veya kontrol edemediğimizde) kaldırmak için bir glob niteleyicisidir . Yalnızca normal dosyalar yerine dizin olmayanları eşleştirmek ^/yerine de kullanabilirsiniz ..

print -rlher bir bağımsız değişken yazdırır çiğ için ayrı ayrı hat .

Herhangi bir zshglob niteleyicisini kullanabilirsiniz , ancak burada her dosya için bir glob genişlettiğimizden , sipariş verenlerin herhangi bir etkisi olmayacağını unutmayın , bu nedenle her biri için sıralanacak tek bir dosya vardır.

(son locatesatırda rapor edilen son dosya yeni satır karakterleriyle (tüm kabuklarda bulunan bir komut değiştirme yanlış özelliği) sona ererse başarısız olabileceğini unutmayın ).


3

Bu, diğer cevaplar kadar yetersizdir, ancak belki daha az verimsizdir:

locate --regex --basename "xfce4-keyboard-overlay$" | 
        while IFS= read -r f; do [ -f "$f" ] && printf "%s\n" "$f"; done

(okunabilirlik için iki satıra bölünmüştür). Yukarıdaki boşluk içeren isimleri işleyecektir. IFS=İsimleri işlemek için gerekli gibi görünüyor sondaki elbette, boşluklar ve -rsen ters eğik çizgi kolu sağlar.

locateEğer yeni satırlar içeren yol isimleri mevcutsa “bir şeye geçelim ” yaklaşımı başarısızlığa mahkum olabilir.


Daha fazla bilgi için IFS, okuyun sh(1)veya bash(1) (( * nix sistemi yazarak man shveya burayaman bash girerek ve / veya burada , burada , burada ve / veya burada okuyarak ). Ardından IFS ve Bash'i Anlama : yığın Exchange'de IFS ile satır satır okuyun (5'ten fazla oy içeren cevaplara odaklanın) ve hâlâ yetmediyseniz, Greg'in Wiki ve IFS arama sonuçlarında IFS'ye bakın Bash Hackers Wiki'de (Stack Exchange'de değil).


ifadenizden sonra "IFS =" hakkında biraz bilgi ekleyebilir misiniz while?
robert

Ben de öyle yaptım.
G-Man

ters eğik çizgiler birçok yankı uygulamasında sorun olmaya devam edecektir. Rasgele veriler için kullanmalısınızprintf .
Stéphane Chazelas

Orada için "--null" parametresini kullanarak yeni satırlar soruna bir çözüm olabilir locateve güçlendirmek readolarak öneriliyor transnum.blogspot.ie/2008/11/...
robert

@ StéphaneChazelas: İyi nokta. Sabit.
G-Man

2
locate --null --regex --basename "xfce4-keyboard-overlay$" |
  xargs -r0 sh -c 'find "$@" -prune ! -type d' sh

Aslında, göründüğünden bile daha kirli ... ama iyi bir teftiş. Sahte kod gibi davranalım, o zaman yararlı :)
Volker Siegel

1
@Volker: Kötü olduğuna katılıyorum: Örneğinizde /usr/local/share/xfce4-keyboard-overlay ve alt dizinlerini listeleyecektir . Eklemek -maxdepth 0yardımcı olur.
G-Man

Daha da iyi gidiyor ...: Dlocate --regex --basename "xfce4-keyboard-overlay$" | xargs -I % sh -c "test -d % && echo %"
FloHimself

1
Kullanımı xargsile findiyi bir fikir oldu, ben sağlam hale getirmek için kaydetmiştiniz. Umursamıyorsun.
Stéphane Chazelas

1

xargsbelirtirseniz -L 1veya -iparametre belirtirseniz her satır için komutu tekrarlar .

Buraya bakın

$ locate --regex --basename "xfce4-keyboard-overlay$" | xargs -i bash -c '(test -d "{}" && echo "{}")'

Kuşkusuz, her dosya için yeni bir kabuk tekmeliyor, ancak güzel ve kompakt olma avantajına sahip.

EDIT: Ben bu cevap ile pek memnun değildi çünkü her dosya için yeni bir kabuk tekme oldu. Bunun sadece iki süreci olmalıdır:

$ locate --regex --basename "xfce4-keyboard-overlay$" | xargs -i echo 'test -d "{}" && echo "{}"' | bash

Tabii ki bir tercümanı tekmelemekten kaçınmak iyi olurdu, ama xargskomutları zincirleme yeteneğinde hamstrung gibi görünüyor.


3
Bu sadece benim makineyi yeniden başlattı (adlı bir dosya vardı /home/evil/$(reboot)/xfce4-keyboard-overlayve ben aptalca olarak çalıştırdı root).
Stéphane Chazelas

2
@ StéphaneChazelas "kökten rastgele rasgele kodz" çalıştırma cesareti için +1;) (scnr)
Volker Siegel

0

Benim görüşüm:

while IFS= read i; \
do \
  if [ -f "$i" ]; \
  then \
    echo "$i"; \
  fi; \
done < <(locate --regex --basename "xfce4-keyboard-overlay$")

Bu, G-Man'ın işlem ikamesi ile birleştirdiği yöntemdir.


Aslında, bu, işlem ikamesi ile birleştiğinde, ters eğik çizgiler içeren veya boşluk bırakan dosya adlarını işleme yeteneği eksi olarak az çok yaptığım yöntemdi . Ayrıca, soru başlığının "dizinleri hariç tut" yazdığını ve bu yanıtın yalnızca dizinleri içerdiğini unutmayın .
G-Man,

Üzgünüm. Benim hatam. Düzeltildi.
Tristan Storch

-1

Ya ve locateile birleşirseniz ? ...filegrep

$ for f in `locate --regex --basename "xfce4-keyboard-overlay$"`; do file $f; done | grep -vi directory

Test etmedim, ama bunun yavaş olabileceğini düşünüyorum, çünkü fileher yol için bir süreç yaratıyor . Tespit için genellikle çok sayıda sonuç satırı olduğuna dikkat edin. Mevcut testim "gnome" araması yapıyor ve test etmek için yaklaşık 73000 yol veriyor.
Volker Siegel

2
@Volker: Bundan daha kötü: $fbir dosya olan her şey için, fileprogram bu dosyayı açacak ve ondan okuyacaktır . Tüm yapmanız gereken bir olduğunda bu oldukça pahalı stat(). ………… Ayrıca, adlarında "dizin" içeren dosyalar ("telefon_dizini" gibi) için yanlış sonuçlar verir. …………… (Ayrıca, for f in `…`; do …sözdizimi boşluk içeren adları işleyemez.)
G-Man,
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.