Dosyanın herhangi bir yerinde birden fazla anahtar kelime içeren dosyaları bulun


16

Aradığım anahtar kelimelerin tam setini içeren bir dizindeki tüm dosyaları listelemenin bir yolunu arıyorum, dosyanın herhangi bir yerinde.

Bu nedenle, anahtar kelimelerin aynı satırda görünmesi gerekmez.

Bunu yapmanın bir yolu:

grep -l one $(grep -l two $(grep -l three *))

Üç anahtar kelime sadece bir örnektir, iki veya dört gibi de olabilir.

Düşünebileceğim ikinci bir yol:

grep -l one * | xargs grep -l two | xargs grep -l three

Başka bir soruda ortaya çıkan üçüncü bir yöntem :

find . -type f \
  -exec grep -q one {} \; -a \
  -exec grep -q two {} \; -a \
  -exec grep -q three {} \; -a -print

Ama bu kesinlikle buraya gittiğim yön değil . Ben az yazar bir şey istiyorum, ve muhtemelen sadece bir çağrı için grep, awk,perl veya benzeri.

Örneğin, nasıl awk tüm anahtar kelimeleri içeren satırları eşleştirmenize izin seviyorum:

awk '/one/ && /two/ && /three/' *

Veya yalnızca dosya adlarını yazdırın:

awk '/one/ && /two/ && /three/ { print FILENAME ; nextfile }' *

Ancak, anahtar kelimelerin mutlaka aynı satırda değil, dosyanın herhangi bir yerinde olabileceği dosyaları bulmak istiyorum.


Örnek için tercih edilen çözümler, gzip dost olurdu grepvardır zgrepvaryantı sıkıştırılmış dosyalar üzerinde olduğunu çalışır. Neden bahsetmiyorum, bu kısıtlama göz önüne alındığında bazı çözümlerin iyi çalışmayabileceğidir. Örneğin, awkeşleşen dosyaları yazdırma örneğinde şunları yapamazsınız:

zcat * | awk '/pattern/ {print FILENAME; nextfile}'

Komutu önemli ölçüde değiştirmeniz gerekiyor:

for f in *; do zcat $f | awk -v F=$f '/pattern/ { print F; nextfile }'; done

Bu nedenle, kısıtlama nedeniyle, awksıkıştırılmamış dosyalarla yalnızca bir kez yapabilseniz bile, birçok kez aramanız gerekir . Ve kesinlikle, zawk '/pattern/ {print FILENAME; nextfile}' *aynı etkiyi yapmak ve elde etmek daha güzel olurdu , bu yüzden buna izin veren çözümleri tercih ederim.


1
gzipDost olmalarına gerek yok , sadece zcatönce dosyalar.
terdon

@terdon Dosyaların neden sıkıştırıldığından bahsettiğimi açıklayarak yayını düzenledim.
arekolek

Awk'yi bir veya birkaç kez başlatmak arasında çok fazla fark yoktur. Yani, tamam, küçük bir ek yük ama fark fark bile edecektim. Elbette, awk / perl komut dosyasını her ne yaparsa yapsın bunu yapmak mümkündür, ancak bu hızlı bir tek satırlık değil, tam gelişmiş bir program olmaya başlar. İstediğin bu mu?
terdon

@terdon Şahsen benim için daha önemli olan nokta, komutun ne kadar karmaşık olacağı (sanırım siz ikinci yorumum siz yorum yaparken geldi). Örneğin, grepçözümler yalnızca grepçağrıları a ile ön ekleyerek kolayca uyarlanabilir z, dosya adlarını da ele almam gerekmiyor.
arekolek

Evet, ama bu grep. AFAIK, sadece grepve catstandart "z-varyantlarına" sahiptir. Bir for f in *; do zcat -f $f ...çözüm kullanmaktan daha basit bir şey elde edeceğinizi sanmıyorum . Başka bir şey, açmadan önce dosya biçimlerini kontrol eden veya aynısını yapmak için bir kitaplık kullanan tam bir program olmalıdır.
terdon

Yanıtlar:


13
awk 'FNR == 1 { f1=f2=f3=0; };

     /one/   { f1++ };
     /two/   { f2++ };
     /three/ { f3++ };

     f1 && f2 && f3 {
       print FILENAME;
       nextfile;
     }' *

Otomatik gzip'lenmiş dosyaları işlemek, ya bir döngü içinde bu çalıştırmak istiyorsanız zcat(eğer bölmek olacak çünkü yavaş ve verimsiz awkher dosya için bir kere, bir döngü içinde birçok kez) ya da aynı algoritmayı yeniden yazmak perlve kullanmak IO::Uncompress::AnyUncompresskütüphane modülü hangi can sıkıştırılmış dosyaları (gzip, zip, bzip2, lzop) birkaç farklı tür sıkıştırmasını açın. veya sıkıştırılmış dosyaları işlemek için modülleri olan python'da.


Aşağıda , herhangi bir sayıda desene ve herhangi bir sayıda dosya adına (düz metin veya sıkıştırılmış metin içeren) izin vermek için perlkullanılan bir sürüm bulunmaktadır IO::Uncompress::AnyUncompress.

Önceki tüm argümanlar --arama örüntüsü olarak ele alınır. Sonraki tüm argümanlar --dosya adı olarak kabul edilir. Bu iş için ilkel ama etkili seçenek işleme. Daha iyi seçenek işleme (örn. Büyük / -iküçük harf duyarlı olmayan aramalar için bir seçeneği desteklemek için) Getopt::StdveyaGetopt::Long modülleriyle .

Şu şekilde çalıştırın:

$ ./arekolek.pl one two three -- *.gz *.txt
1.txt.gz
4.txt.gz
5.txt.gz
1.txt
4.txt
5.txt

(Dosyaları listelemeyeceğim {1..6}.txt.gzve {1..6}.txtburada ... test için sadece "bir" "iki" "üç" "dört" "beş" ve "altı" kelimelerinin bir kısmını veya tamamını içeriyorlar. Yukarıdaki çıktıda listelenen dosyalar Arama modellerinin üçünü de YAPIN: Kendi verilerinizle kendiniz test edin)

#! /usr/bin/perl

use strict;
use warnings;
use IO::Uncompress::AnyUncompress qw(anyuncompress $AnyUncompressError) ;

my %patterns=();
my @filenames=();
my $fileargs=0;

# all args before '--' are search patterns, all args after '--' are
# filenames
foreach (@ARGV) {
  if ($_ eq '--') { $fileargs++ ; next };

  if ($fileargs) {
    push @filenames, $_;
  } else {
    $patterns{$_}=1;
  };
};

my $pattern=join('|',keys %patterns);
$pattern=qr($pattern);
my $p_string=join('',sort keys %patterns);

foreach my $f (@filenames) {
  #my $lc=0;
  my %s = ();
  my $z = new IO::Uncompress::AnyUncompress($f)
    or die "IO::Uncompress::AnyUncompress failed: $AnyUncompressError\n";

  while ($_ = $z->getline) {
    #last if ($lc++ > 100);
    my @matches=( m/($pattern)/og);
    next unless (@matches);

    map { $s{$_}=1 } @matches;
    my $m_string=join('',sort keys %s);

    if ($m_string eq $p_string) {
      print "$f\n" ;
      last;
    }
  }
}

Karma %patterns, dosyaların her bir üyeden en az birini içermesi gereken tam desen kümesini içerir ve $_pstringbu karma işleminin sıralanmış anahtarlarını içeren bir dizedir. Dize $pattern, karmadan oluşturulmuş önceden derlenmiş bir normal ifade içerir %patterns.

$patternher girdi dosyasının her satırıyla karşılaştırılır ( çalışma sırasında hiç değişmeyeceğini bildiğimiz gibi yalnızca bir kez /oderlemek için değiştiriciyi kullanarak $pattern) vemap() her dosya için eşleşmeleri içeren bir karma (% s) oluşturmak için kullanılır.

Geçerli desende tüm desenler görüldüğünde ( $m_string(sıralanan tuşlar %s) eşit olup olmadığını karşılaştırarak $p_string), dosya adını yazdırın ve bir sonraki dosyaya geçin.

Bu özellikle hızlı bir çözüm değildir, ancak makul olmayan bir şekilde yavaş değildir. İlk sürüm 4m58 aldı ve 74MB değerinde sıkıştırılmış günlük dosyasında (toplam 937MB sıkıştırılmamış) üç kelime aradı. Bu güncel sürüm 1m13s alır. Muhtemelen yapılabilecek başka optimizasyonlar vardır.

Bariz bir optimizasyon bunu paralel olarak dosyaların alt kümelerinde birden çok arama yapmak için xargs' -Paka ' ile birlikte kullanmaktır --max-procs. Bunu yapmak için, dosya sayısını saymanız ve sisteminizin sahip olduğu çekirdek / cpus / iş parçacığı sayısına bölmeniz (ve 1 ekleyerek yuvarlamanız) gerekir. Örneğin, örnek setimde 269 dosya arandı ve sistemim 6 çekirdeğe (AMD 1090T) sahip, bu yüzden:

patterns=(one two three)
searchpath='/var/log/apache2/'
cores=6
filecount=$(find "$searchpath" -type f -name 'access.*' | wc -l)
filespercore=$((filecount / cores + 1))

find "$searchpath" -type f -print0 | 
  xargs -0r -n "$filespercore" -P "$cores" ./arekolek.pl "${patterns[@]}" --

Bu optimizasyonla, eşleşen 18 dosyanın tümünü bulmak sadece 23 saniye sürdü. Tabii ki, aynı diğer çözümlerden herhangi biri için de yapılabilir. NOT: Çıktıda listelenen dosya adlarının sırası farklı olacaktır, bu nedenle daha sonra sıralanması gerekebilir.

@Arekolek tarafından belirtildiği gibi, veya zgrepile birden fazla sfind -execxargs daha hızlı bir şekilde yapabilir, ancak bu komut dosyası, aramak için herhangi bir sayıda deseni destekleme avantajına sahiptir ve birkaç farklı sıkıştırma türüyle başa çıkabilir.

Komut dosyası her dosyanın yalnızca ilk 100 satırını incelemekle sınırlıysa, bunların hepsini (74MB 269 dosya örneğimde) 0.6 saniye içinde çalıştırır. Bu bazı durumlarda yararlıysa, bir komut satırı seçeneğine (örn. -l 100) Dönüştürülebilir, ancak eşleşen tüm dosyaları bulamama riski vardır .


BTW, kılavuz sayfasına göre IO::Uncompress::AnyUncompress, desteklenen sıkıştırma formatları şunlardır:

  • zlib RFC 1950 ,
  • RFC 1951'i söndürün (isteğe bağlı),
  • gzip RFC 1952 ,
  • zip,
  • bzip2,
  • lzop,
  • lzf,
  • lzma,
  • xz

Son bir (umarım) optimizasyon. Onun yerine ( PerlIO::gzipdebian olarak paketlenmiş) modülü kullanarak 74MB günlük dosyalarımı işlemek için yaklaşık 3.1 saniyeye kadar zaman aldım . Bunun yerine basit bir karma kullanarak da bazı küçük iyileştirmeler yapıldı (bu da sürümle birkaç saniye tasarruf etti ).libperlio-gzip-perlIO::Uncompress::AnyUncompressSet::ScalarIO::Uncompress::AnyUncompress

PerlIO::gzip/programming//a/1539271/137158 (için bir google aramasıyla bulundu perl fast gzip decompress) içinde en hızlı perl gunzip olarak önerildi

xargs -PBununla kullanmak hiç iyileştirmedi. Aslında 0.1 ila 0.7 saniye arasında herhangi bir yere yavaşlamış gibi görünüyordu. (Dört çalışmayı denedim ve sistemim arka planda zamanlamayı değiştirecek başka şeyler yapıyor)

Fiyat, komut dosyasının bu sürümünün yalnızca gzip edilmiş ve sıkıştırılmamış dosyaları işleyebilmesidir. Hız ve esneklik: Bu sürüm için 3.1 saniye ve bir IO::Uncompress::AnyUncompresssürüm için 23 saniyexargs -P ve sarıcılı (veya 1m13s olmadan xargs -P).

#! /usr/bin/perl

use strict;
use warnings;
use PerlIO::gzip;

my %patterns=();
my @filenames=();
my $fileargs=0;

# all args before '--' are search patterns, all args after '--' are
# filenames
foreach (@ARGV) {
  if ($_ eq '--') { $fileargs++ ; next };

  if ($fileargs) {
    push @filenames, $_;
  } else {
    $patterns{$_}=1;
  };
};

my $pattern=join('|',keys %patterns);
$pattern=qr($pattern);
my $p_string=join('',sort keys %patterns);

foreach my $f (@filenames) {
  open(F, "<:gzip(autopop)", $f) or die "couldn't open $f: $!\n";
  #my $lc=0;
  my %s = ();
  while (<F>) {
    #last if ($lc++ > 100);
    my @matches=(m/($pattern)/ogi);
    next unless (@matches);

    map { $s{$_}=1 } @matches;
    my $m_string=join('',sort keys %s);

    if ($m_string eq $p_string) {
      print "$f\n" ;
      close(F);
      last;
    }
  }
}

for f in *; do zcat $f | awk -v F=$f '/one/ {a++}; /two/ {b++}; /three/ {c++}; a&&b&&c { print F; nextfile }'; doneiyi çalışıyor, ama gerçekten benim çözümümden 3 kat daha uzun sürüyor grepve aslında daha karmaşık.
arekolek

1
OTOH, düz metin dosyaları için daha hızlı olurdu. ve benim önerdiğim gibi sıkıştırılmış dosyaları (perl veya python gibi) okuma desteği ile bir dilde uygulanan aynı algoritma birden çok greps daha hızlı olacaktır. "komplikasyon" kısmen sübjektiftir - kişisel olarak, tek bir awk veya perl veya python betiği bulup veya bulmadan çoklu açılmadan daha az karmaşık olduğunu düşünüyorum .... @ terdon'un cevabı iyidir ve bahsettiğim modüle ihtiyaç duymadan yapar (ancak her sıkıştırılmış dosya için zcat çatallama pahasına)
cas

apt-get install libset-scalar-perlSenaryoyu kullanmak zorunda kaldım . Ancak makul bir sürede sona ermiyor gibi görünüyor.
arekolek

aradığınız dosyalar kaç tane ve hangi boyutta (sıkıştırılmış ve sıkıştırılmamış)? düzinelerce veya yüzlerce küçük-orta boy dosya veya binlerce büyük dosya?
cas

Sıkıştırılmış dosya boyutlarının bir histogramı (20 ila 100 dosya, 50 MB'a kadar ancak çoğunlukla 5 MB'nin altında). Sıkıştırılmamış aynı görünmek, ancak boyutları 10 ile çarpılır.
arekolek

11

Kayıt ayırıcıyı, tüm dosyayı tek bir satır olarak ele alacak .şekilde ayarlayın awk:

awk -v RS='.' '/one/&&/two/&&/three/{print FILENAME}' *

Benzer şekilde perl:

perl -ln00e '/one/&&/two/&&/three/ && print $ARGV' *

3
Temiz. Bunun tüm dosyayı belleğe yükleyeceğini ve büyük dosyalar için bir sorun olabileceğini unutmayın.
terdon

Başlangıçta bunu iptal ettim, çünkü umut verici görünüyordu. Ama gzip'lenmiş dosyalarla çalışmasını sağlayamıyorum. for f in *; do zcat $f | awk -v RS='.' -v F=$f '/one/ && /two/ && /three/ { print F }'; donehiçbir şey çıkarmaz.
arekolek

@arekolek Bu döngü benim için çalışıyor. Dosyalarınız düzgün bir şekilde sıkıştırılmış mı?
jimmij

@arekolek zcat -f "$f"dosyalardan bazıları sıkıştırılmamışsa gerekir.
terdon

Ben de sıkıştırılmamış dosyalarda test ve awk -v RS='.' '/bfs/&&/none/&&/rgg/{print FILENAME}' greptest/*.txthala hiçbir sonuç grep -l rgg $(grep -l none $(grep -l bfs greptest/*.txt))döndürürken, beklenen sonuçları döndürür.
arekolek

3

Sıkıştırılmış dosyalar için, her bir dosya üzerinde döngü yapabilir ve ilk önce açabilirsiniz. Ardından, diğer cevapların biraz değiştirilmiş bir versiyonuyla şunları yapabilirsiniz:

for f in *; do 
    zcat -f "$f" | perl -ln00e '/one/&&/two/&&/three/ && exit(0); }{ exit(1)' && 
        printf '%s\n' "$f"
done

Perl betiği, 0üç dizenin tümü de bulunursa durumla (başarılı) çıkacaktır . }{Perl steno içindirEND{} . Takip eden her şey, tüm girdiler işlendikten sonra yürütülür. Bu nedenle, tüm dizeler bulunmazsa komut dosyası 0 dışı bir çıkış durumuyla çıkar. bu yüzden&& printf '%s\n' "$f" dosya adını yalnızca üçü de bulunursa yazdırır.

Veya dosyayı belleğe yüklemekten kaçınmak için:

for f in *; do 
    zcat -f "$f" 2>/dev/null | 
        perl -lne '$k++ if /one/; $l++ if /two/; $m++ if /three/;  
                   exit(0) if $k && $l && $m; }{ exit(1)' && 
    printf '%s\n' "$f"
done

Son olarak, her şeyi bir senaryoda gerçekten yapmak istiyorsanız, şunları yapabilirsiniz:

#!/usr/bin/env perl

use strict;
use warnings;

## Get the target strings and file names. The first three
## arguments are assumed to be the strings, the rest are
## taken as target files.
my ($str1, $str2, $str3, @files) = @ARGV;

FILE:foreach my $file (@files) {
    my $fh;
    my ($k,$l,$m)=(0,0,0);
    ## only process regular files
    next unless -f $file ;
    ## Open the file in the right mode
    $file=~/.gz$/ ? open($fh,"-|", "zcat $file") : open($fh, $file);
    ## Read through each line
    while (<$fh>) {
        $k++ if /$str1/;
        $l++ if /$str2/;
        $m++ if /$str3/;
        ## If all 3 have been found
        if ($k && $l && $m){
            ## Print the file name
            print "$file\n";
            ## Move to the net file
            next FILE;
        }
    }
    close($fh);
}

Yukarıdaki komut dosyasını foo.pliçinde herhangi bir yerde kaydedin $PATH, çalıştırılabilir yapın ve şu şekilde çalıştırın:

foo.pl one two three *

2

Şimdiye kadar önerilen tüm çözümler arasında, grep kullanan orijinal çözümüm en hızlı çözümdür ve 25 saniyede tamamlanır. Bunun dezavantajı, anahtar kelime eklemek ve kaldırmak sıkıcıdır. Bu nedenle multi, davranışı simüle eden, ancak sözdizimini değiştirmeye izin veren bir komut dosyası (dublaj ) ile geldim :

#!/bin/bash

# Usage: multi [z]grep PATTERNS -- FILES

command=$1

# first two arguments constitute the first command
command_head="$1 -le '$2'"
shift 2

# arguments before double-dash are keywords to be piped with xargs
while (("$#")) && [ "$1" != -- ] ; do
  command_tail+="| xargs $command -le '$1' "
  shift
done
shift

# remaining arguments are files
eval "$command_head $@ $command_tail"

Şimdi, yazmak multi grep one two three -- *orijinal teklifime eşdeğer ve aynı zamanda çalışıyor. Sıkıştırılmış dosyalarda zgrepda ilk argüman olarak kolayca kullanabilirim .

Diğer çözümler

Ayrıca, iki strateji kullanarak bir Python betiği ile denedim: tüm anahtar kelimeleri satır satır arama ve tüm dosya anahtar sözcüğünü anahtar kelimeye göre arama. İkinci strateji benim durumumda daha hızlıydı. Ama grep33 saniyede bitirmek sadece kullanmaktan daha yavaştı . Satır satır satır anahtar kelime eşleme 60 saniyede tamamlandı.

#!/usr/bin/python3

import gzip, sys

i = sys.argv.index('--')
patterns = sys.argv[1:i]
files = sys.argv[i+1:]

for f in files:
  with (gzip.open if f.endswith('.gz') else open)(f, 'rt') as s:
    txt = s.read()
    if all(p in txt for p in patterns):
      print(f)

Terdon tarafından verilen komut dosyası 54 saniyede tamamladı. Aslında 39 saniye duvar süresi aldı, çünkü işlemcim çift çekirdekli. Bu ilginç, çünkü Python betiğim 49 saniye duvar süresi aldı (ve grep29 saniye idi).

Cas tarafından yazı bile işlenmiştir dosyaların daha az sayıda, makul bir süre içinde sona erdirmek için başarısız greponu öldürmek zorunda, 4 saniyenin altında.

Ancak orijinal awkönerisi, eskisinden daha yavaş olmasına rağmen grep, potansiyel bir avantaja sahiptir. Bazı durumlarda, en azından deneyimlerime göre, tüm anahtar kelimelerin dosyada varsa, dosyanın başında bir yerde görünmesini beklemek mümkündür. Bu, bu çözüme performansta çarpıcı bir artış sağlar:

for f in *; do
  zcat $f | awk -v F=$f \
    'NR>100 {exit} /one/ {a++} /two/ {b++} /three/ {c++} a&&b&&c {print F; exit}'
done

25 saniyenin aksine saniyenin çeyreğinde biter.

Tabii ki, dosyaların başlangıcına yakın olduğu bilinen anahtar kelimeleri arama avantajımız olmayabilir. Böyle bir durumda, çözüm NR>100 {exit}63 saniye sürer (50s duvar süresi).

Sıkıştırılmamış dosyalar

grepÇözümümün ve cas'in awkönerisi arasında çalışma süresinde önemli bir fark yoktur , her ikisinin de yürütülmesi bir saniyenin bir kısmını alır.

FNR == 1 { f1=f2=f3=0; }Bu durumda, sonraki işlenen her dosya için sayaçları sıfırlamak üzere değişken başlatmanın zorunlu olduğunu unutmayın . Bu nedenle, bir anahtar kelimeyi değiştirmek veya yenilerini eklemek istiyorsanız, komutun üç yerde düzenlenmesini gerektirir. Öte yandan, grepsadece| xargs grep -l four istediğiniz anahtar kelimeyi veya düzenleyebilirsiniz.

grepKomut ikamesi kullanan bir çözümün dezavantajı , zincirin herhangi bir yerinde, son adımdan önce eşleşen dosya yoksa asılı kalmasıdır. Bu, xargsvaryantı etkilemez çünkü boru grepsıfırdan farklı bir durum döndürüldüğünde durdurulur . Senaryoyu kullanacak xargsşekilde güncelledim , bu yüzden betiği daha basit hale getirmek zorunda kalmam.


Python çözümünüz, döngüyü C katmanına doğru itmekten yararlanabilirnot all(p in text for p in patterns)
iruvar

@iruvar Öneri için teşekkürler. Ben denedim (sans not) ve 32 saniye içinde bitmiş, bu yüzden çok fazla gelişme değil, ama kesinlikle daha okunabilir.
arekolek

awk içinde f1, f2, f3 yerine ilişkisel bir dizi kullanabilirsiniz, key = search-pattern, val = count
cas

@arekolek PerlIO::gzipyerine benim son sürümü görmek IO::Uncompress::AnyUncompress. 74MB günlük dosyalarımı işlemek için 1m13 yerine yalnızca 3,1 saniye sürüyor.
cas

BTW, daha önce eval $(lesspipe)(ör. .profile, Vb.) Çalıştırdıysanız , lessyerine kullanabilirsiniz zcat -fve fordöngü sarmalayıcı (gzip, bzip2, xz ve daha fazlası) awkher türlü dosyayı lessişleyebilecektir .... stdout'un bir boru olup olmadığını daha az tespit edebilir ve sadece stdout'a bir akış çıkarır.
cas

0

Başka bir seçenek - kelimeleri dosyaya karşı xargsçalışması için birer birer besleyin grep. geri dönme xargsçağrısının grepgeri dönmesi çağrısına geri dönülürse kendiliğinden çıkılabilir 255( xargsbelgelere bakın). Tabii ki bu çözeltiye mermilerin yumurtlanması ve çatallanması önemli ölçüde yavaşlatacaktır.

printf '%s\n' one two three | xargs -n 1 sh -c 'grep -q $2 $1 || exit 255' _ file

ve döngüye sokmak

for f in *; do
    if printf '%s\n' one two three | xargs -n 1 sh -c 'grep -q $2 $1 || exit 255' _ "$f"
    then
         printf '%s\n' "$f"
    fi
done

Bu hoş görünüyor, ama bunu nasıl kullanacağımdan emin değilim. Nedir _ve file? Bu, bağımsız değişken olarak iletilen ve tüm anahtar kelimeleri içeren dosyaları döndürecek birden fazla dosyada mı arama yapacak?
arekolek

@arekolek, bir döngü sürümü ekledi. Ve gelince _, o kadar geçirilen ediliyor $0bu çıkışında komut adı olarak göstermek istiyorum - kökenli kabuğuna psben ertelemek istiyorum - usta burada
Iruvar
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.