GNU araçlarıyla:
find . -type f -exec grep -lZ FIND {} + | xargs -r0 grep -l ME
Standart olarak şunları yapabilirsiniz:
find . -type f -exec grep -q FIND {} \; -exec grep -l ME {} \;
Ancak bu, dosya başına iki greft çalıştırır. grep
Dosya adlarında herhangi bir karaktere izin verirken bu kadar çok s'yi çalıştırmayı ve yine de taşınabilir olmayı önlemek için şunları yapabilirsiniz:
convert_to_xargs() {
sed "s/[[:blank:]\"\']/\\\\&/g" | awk '
{
if (NR > 1) {
printf "%s", line
if (!index($0, "//")) printf "\\"
print ""
}
line = $0
}'
END { print line }'
}
find .//. -type f |
convert_to_xargs |
xargs grep -l FIND |
convert_to_xargs |
xargs grep -l ME
Çıkışı, tek, çift tırnak işaretleri ve ters eğik çizgilerin olabileceği ayrılmış bir kelime listesi olan find
xargs (boş bir boşluk (SPC / TAB / NL ve yerel ayarınızdaki diğer boşluklar) ile ilgili bir biçime dönüştürmektir. xargs
boşlukları ve birbirleri kaçış).
Genellikle find -print
, dosya adlarını yeni satır karakteriyle ayırdığı ve dosya adlarında bulunan yeni satır karakterlerinden çıkmadığı için çıktısını sonradan işleyemezsiniz . Örneğin:
./a
./b
Bunun b
bir dizinde adlandırılan bir dosya a<NL>.
mı yoksa iki dosya a
ve mı olduğunu bilmenin bir yolu yok b
.
Kullanarak .//.
, //
başka bir şekilde çıktı olarak bir dosya yolunda görünemediğinden find
(boş bir ada sahip bir dizin diye bir şey /
olmadığı ve dosya adında izin verilmediği için), içeren bir satır görürsek //
, yeni bir dosya adının ilk satırı. Bu awk
komutu, bu satırlardan önce gelen tüm yeni satır karakterlerinden kaçmak için kullanabiliriz .
Yukarıdaki örneği alırsak find
, ilk durumda çıktı alır (bir dosya):
.//a
./b
Hangi awk kaçar:
.//a\
./b
Bu xargs
onu tek bir argüman olarak görüyor. Ve ikinci durumda (iki dosya):
.//a
.//b
Hangi awk
olduğu gibi xargs
bırakılır , böylece iki argüman görür.