Dizindeki dosyalar adında belirli bir dize ile sayılsın mı?


12

Aşağıdaki dosyaları var:

Codigo-0275_tdim.matches.tsv  
Codigo-0275_tdim.snps.tsv  
FloragenexTdim_haplotypes_SNp3filter17_single.tsv  
FloragenexTdim_haplotypes_SNp3filter17.tsv  
FloragenexTdim_SNP3Filter17.fas  
S134_tdim.alleles.tsv    
S134_tdim.snps.tsv  
S134_tdim.tags.tsv

Adında snp(büyük / küçük harf) kelimesi olan dosya sayısını saymak istiyorum . Kullanmayı denedim

grep -a 'snp' | wc -l   

ama sonra grepdosyaların içinde arama yaptığını fark ettim . Dosya adlarını taramak için doğru komut nedir?


1
Bu sitede "sayım dosyaları" için arama yapmayı denediniz mi?
don_crissti

Yanıtlar:


18

snpDosya adlarında mı aramak istiyorsunuz ? Bu, aşağıdaki gibi kullanılan basit bir kabuk glob (joker karakter) olurdu:

ls -dq *snp* | wc -l

-qSürümünüz lstanımıyorsa bayrağı atlayın . "Tuhaf" karakterler içeren dosya adlarını (yeni satırlar dahil) işler.


İçinde lsbelirli bir metin bulunan dosya adlarını almak için kullanabileceğimden emin değildim . Yine de işe yaradı, teşekkürler.
Lucia O

@LuciaO yorumunuzu tekrar okuyor ls, dosya adlarıyla eşleşen değil , kabuk. lskalıpla eşleşen dosyaların bir listesini görür; o mu değil deseni kendisi bkz.
roaima

2
Geri dönen çok fazla dosyanız varsa bu işe yaramayabilir.
Dennis Nolte

4

Unix & Linux koridorlarında sessizce durursanız ve dikkatlice dinlerseniz, acımasızca ağlayan, “Yeni satırlar içeren dosya isimleri ne olacak?”

ls -d *snp* | wc -l

veya aynı şekilde ,

printf "%s\n" *snp* | wc -l

içeren çıktısı her dosya snp, her biri bir yeni satır, ardından aynı zamanda dosya herhangi bir yeni satır da dahil olmak üzere , ve daha sonra çıktı hatlarının sayısı. Adı olan bir dosya varsa

                                f o o s n p \n b a r . t s v

o zaman bu isim şöyle yazılır

foosnp
bar.tsv

elbette ki iki satır olarak sayılır.

En azından bazı durumlarda daha iyisini yapan birkaç alternatif var:

printf "%s\n" * | grep -c snp

içeren satırları sayar snp, bu nedenle foosnp(\n)bar.tsvyukarıdaki örnek yalnızca bir kez sayılır. Bu konuda küçük bir varyasyon

ls -f | grep -c snp

Yukarıdaki iki komut bundan farklıdır:

  • Bu ls -fad, adları ile başlayan dosyaları içerir .; kabuk seçeneği ayarlanmadığı printf … *sürece , bunu yapmaz dotglob.
  • printfbir kabuk yerleşiktir; lsharici bir komuttur. Bu nedenle, lsbiraz daha fazla kaynak kullanabilir.
  • Kabuk a'yı işlediğinde *dosya adlarını sıralar; ls -fdosya adlarını sıralamaz. Bu nedenle, lsbiraz daha az kaynak kullanabilir.

Ancak ortak bir şeyleri var: İkisi de yeni satır içeren vesnp yeni satırdan önce ve sonra bulunan dosya adlarının varlığında yanlış sonuçlar verecektir .

Bir diğeri:

filenamelist=(*snp*)
echo ${#filenamelist[@]}

Bu, içeren tüm dosya adlarını listeleyen bir kabuk dizisi değişkeni oluşturur snpve sonra dizideki öğelerin sayısını bildirir. Dosya adları satır olarak değil, dize olarak ele alınır, bu nedenle katıştırılmış yeni satırlar sorun olmaz. Dizin çok büyükse bu yaklaşımın bir sorunu olabileceği düşünülebilir, çünkü dosya adları listesinin kabuk belleğinde tutulması gerekir.

Yine bir başka:

Daha önce, dediğimizde printf "%s\n" *snp*, printfkomut "%s\n", genişletme işlemindeki her bağımsız değişken için biçim dizesini bir kez tekrarladı (yeniden kullandı) *snp*. Burada, küçük bir değişiklik yapıyoruz:

printf "%.0s\n" *snp* | wc -l

Bu "%.0s\n", genişletme işlemindeki her bağımsız değişken için biçim dizesini bir kez tekrarlar (yeniden kullanır) *snp*. Ancak "%.0s", her dizenin ilk sıfır karakterini yazdırmak anlamına gelir - yani hiçbir şey. Bu printfkomut snp, adında bulunan her dosya için yalnızca yeni satır (yani boş satır) verir ; ve sonra wc -lonları sayar. Ve yine, .dosyaları ayarlayarak dahil edebilirsiniz dotglob.


1

Öz:

"Tek" adlı dosyalar için çalışır (yeni satırlar dahil).

set -- *snp* ; echo "$#"                             # change positional arguments

count=$(printf 'x%.0s' *snp*); echo "${#count}"      # most shells

printf -v count 'x%.0s' *snp*; echo "${#count}"      # bash

Açıklama

Basit bir glob, her dosya snpadını kendi adıyla eşleştireceğinden echo *snp*, bu durum için basit bir yeterli olabilir, ancak gerçekten kullanacağım sadece üç dosya olduğunu göstermek için:

$ ls -Q *snp*
"Codigo-0275_tdim.snps.tsv"  "foo * bar\tsnp baz.tsv"  "S134_tdim.snps.tsv"

Geriye kalan tek sorun dosyaları saymaktır. Evet, grep normal bir çözümdür ve evet yeni satırları saymak wc -lda olağan bir çözümdür. O Not grep -c(sayımı) gerçekten bir kaç kez sayar snpbir dosya adı birden fazla varsa, dize eşleştirilir ve snpadına dize, sayım yanlış olacaktır.

Daha iyisini yapabiliriz.

Basit bir çözüm konumsal argümanları ayarlamaktır:

$ set -- *snp*
$ echo "$#"
3

Konumsal bağımsız değişkenleri değiştirmekten kaçınmak için her bir bağımsız değişkeni bir karaktere dönüştürebilir ve elde edilen dizenin uzunluğunu yazdırabiliriz (çoğu kabuk için):

$ printf 'x%.0s' *snp*
xxx

$ count=$(printf 'x%.0s' *snp*); echo "${#count}"
3

Veya, alt kabuktan kaçınmak için bash'da:

$ printf -v count 'x%.0s' *snp*; echo "${#count}"
3

Dosya listesi

Dosyaların listesi (orijinal sorudan satırsonu eklenmiş olandan):

a='
Codigo-0275_tdim.matches.tsv
Codigo-0275_tdim.snps.tsv
FloragenexTdim_haplotypes_SNp3filter17_single.tsv
FloragenexTdim_haplotypes_SNp3filter17.tsv
FloragenexTdim_SNP3Filter17.fas
S134_tdim.alleles.tsv
S134_tdim.snps.tsv
S134_tdim.tags.tsv'
$ touch $a

touch $'foosnp\nbar.tsv' 

Bunun ortasında bir satırsonu olan bir dosya olacaktır:

f o o s n p \n b a r . t s v

Ve glob genişlemesini test etmek için:

$ touch $'foo * bar\tsnp baz.tsv'

Bu, yıldız işaretini ekler, eğer belirtilmemişse tüm dosya listesine genişler.


-1

html dosyalarının sayısını saymak istediğinizi varsayalım:

ls | grep ".html" | wc -l

"snp" oluşumlarını sayıyorsanız:

ls | grep "snp" | wc -l
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.