Find komutundan sonra bağlayıcıları kullanma


10

Bash'imin find komutunu kullanarak sadece bir şey bulunursa 'found' yazmasını istiyorum. Ama && kullanmak işe yaramaz: hiçbir şey bulunmasa bile, 'bulundu' baskısı alıyorum. Misal:

$ pwd
/data/data/com.termux/files/home/test/test1/test4
$ ls
xaa  xab
$ find . -name xac && echo 'found'
found
$ find . -name xaa && echo 'found'
./xaa
found

Yanıtlar:


18

Sen yapabilir findkendisini yazdırmak found:

find . -name xac -printf "found\n" -quit

-quitYapacak find ilk eşleşmeden sonra çıkın böylece, foundyalnızca bir kez en fazla basılır.

Unix & Linux üzerinde benzer bir iş parçacığında ( hiçbir şey bulunamadığında başarısız olun ), hiçbir şey bulamazsagrep -qz sıfırdan farklı bir çıkış durumu döndürürdüm find:

find /some/path -print0 -quit | grep -qz .

&&Veya komutunu kullanarak bileşik komutlar oluşturmak için kullanabilirsiniz if:

find /some/path -print0 -quit | grep -qz . && echo found

Bir süre buna bakmalıydım. /some/pathNereden bakmaya başlayacağını söyler, ama hiçbir şey ona neye bakacağını söylemez. Bağlantılı cevabınızla aynı. Benim için ne işe yarıyor find /some/path -name xac -print0 -quit | grep -qz . && echo found. Bir şey mi kaçırdım?
Joe

@ Burada önemli olan şey -print0 -quit. Bundan önce ne koyduğunuz, ne bulmak istediğinize bağlıdır. Bunu burada atlamayı seçtim.
muru

13

muru'nun cevabı , dosya bulunursa bir şey yazdırmak istediğimiz durumlar için uygun ve uygundur. Genel durum için harici komut yürütmek istediğimizde, örneğin bayrak echokullanabiliriz -exec.

$ find . -name 'xac' -exec echo "I found " {} \; -quit             
I found  ./xac

{}Parçası arasındaki komut için bir dosya adı geçen -execve \;bağımsız değişkenler olarak. Not \önce ;- bu engeller yanlış yorumlayarak gelen kabuk; noktalı virgül anlamına hangi komutun sonuna fakat eğik çizgiyle zaman, kabuk geçirilecek literall metin olarak algılar kabuk kapanış findkomuta ve kapanış olarak hizmet veren komutu bulmak için -execbayrağı'nın argümanlar.


if found do this; else do thatSıralama koşullarını oluşturmak için, komut alt bölümünü $()ve test(aka [) komutunu kullanabiliriz :

$ [ "x$(find . -name 'noexist' -print -quit)" != "x" ] && echo "found" || echo "not found"                                                                                              
not found

$ [ "x$(find . -name 'xac' -print -quit)" != "x" ] && echo "found" || echo "not found"                                                                                                  
found

Dan'ın yorumuna değinmek

Dan yorumlarda sordu:

"{}" Bulduğum yankı "{" bulduğum "yankıdan daha iyi olmaz mıydı? Belki yankı için sorun değil, ama birisi komutu kopyalar ve yankıyı başka bir komutla değiştirirse sorun yaşayabilir

Önce sorunu anlayalım. Genellikle, kabuklarda sözcük bölme kavramı vardır, bu da alıntılanmamış değişkenler ve konumsal parametrelerin genişletileceği ve ayrı öğeler olarak ele alınacağı anlamına gelir. Örneğin, değişken varsa varve içerdiği hello worldmetni bunu yaptığında, touch $varkabuk iki ayrı öğeler içine yıkmak olacak hellove worldve touchsize 2 ayrı dosya oluşturmak için çalışıyormuş gibi olduğunu anlayacaktır; bunu yaparsanız touch "$var", kabuk hello worldtek bir birim gibi davranır ve touchyalnızca bir dosya oluşturur. Bunun sadece mermilerin nasıl çalıştığından dolayı olduğunu anlamak önemlidir.

Aksine, findbu tür davranışlardan muzdarip değildir, çünkü komutlar findkendi kendine işlenir ve execvp()sistem çağrısı tarafından yürütülür , bu nedenle herhangi bir kabuk yoktur. Kıvırcık parantezlerin kabuklarda özel bir anlamı findolsa da, başlangıçta değil , komutun ortasında görünürler , bu durumda kabuk için özel bir anlam taşımazlar. İşte bir örnek. Birkaç zor dosya adı oluşturalım ve bunları statkomuta argümanı olarak geçirmeye çalışalım .

$ touch with$'\t'tab.txt with$' 'space.txt with$'\n'newline.txt

$ find -type f -exec stat -c "%F" {} \; -print                                                                                                                         
regular empty file
./with?newline.txt
regular empty file
./with space.txt
regular empty file
./with?tab.txt

Gördüğünüz gibi, statzor dosya adlarını mükemmel şekilde alır find, bu da taşınabilir komut dosyalarında kullanılmasının önerilmesinin ana nedenlerinden biridir ve özellikle dizin ağacında gezinirken ve potansiyel olarak olabilecek dosya adlarıyla bir şey yapmak istediğinizde yararlıdır özel karakterler. Bu nedenle, çalıştırılan komutlar için süslü parantez alıntılamak gerekli değildir find.

Mermi karıştığında farklı bir hikaye. Bazen dosya adını işlemek için bir kabuk kullanmanız gerekir. Bu durumda, alıntı yapmak gerçekten önemli olacaktır, ancak bulmanın problemi olmadığını fark etmek önemlidir - kelime bölünmesini yapan kabuktur.

$ find -type f -exec bash -c "stat {}" sh \;   
stat: cannot stat './with': No such file or directory
sh: line 1: newline.txt: command not found
stat: cannot stat './with': No such file or directory
stat: cannot stat 'space.txt': No such file or directory
stat: cannot stat './with': No such file or directory
stat: cannot stat 'tab.txt': No such file or directory

Kabuk içinde alıntı yaptığımızda işe yarayacak. Ama yine, bu kabuk için önemli, değil find.

$ find -type f -exec bash -c "stat -c '%F' '{}'" sh \;                                                                                                                 
regular empty file
regular empty file
regular empty file

Bundan echo "I found {}"daha iyi olmaz mıydı echo "I found " {}? Belki echo için sorun değil, ama birisi komutu kopyalar ve echo yerine başka bir komut koyarsa, bir problemleri olabilir.
Dan

@Konu yorumlarda tartışmak için çok uzundu, bu yüzden cevabımda bir düzenleme yaptım. Lütfen bakın
Sergiy Kolodyazhnyy

1
Sonunda bu noktalı virgülün neden orada olması gerektiğini anlamam için teşekkür ederim. Ayrıca, alıntı büyük açıklama.
Joe

1
Yorumuma cevap olarak çok fazla ayrıntı beklemiyordum. Bu açıklamayı çok takdir ediyorum, teşekkürler!
Dan
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.