Hitung file dalam direktori dengan string spesifik pada nama?

12

Saya memiliki file-file berikut:

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

Saya ingin menghitung jumlah file yang memiliki kata snp(sensitif huruf) pada namanya. Saya mencoba menggunakan

grep -a 'snp' | wc -l   

tapi kemudian saya menyadari bahwa greppencarian di dalam file. Apa perintah yang benar untuk memindai melalui nama file?

Lucia O
sumber
1
Sudahkah Anda mencoba mencari situs ini untuk "menghitung file"?
don_crissti

Jawaban:

18

Apakah Anda bermaksud mencari namasnp file ? Itu akan menjadi shell glob sederhana (wildcard), digunakan seperti ini:

ls -dq *snp* | wc -l

Abaikan -qbendera jika versi lsAnda tidak mengenalinya. Ini menangani nama file yang mengandung karakter "aneh" (termasuk baris baru).

roaima
sumber
Tidak yakin apakah saya bisa menggunakannya lsuntuk mengambil nama file dengan teks tertentu di dalamnya. Tapi itu berhasil, terima kasih.
Lucia O
@LuciaO membaca kembali komentar Anda, itu tidak lscocok dengan nama file, itu shell. lsmelihat daftar file yang cocok dengan polanya; itu tidak melihat pola itu sendiri.
roaima
2
perhatikan ini mungkin tidak berfungsi jika Anda memiliki terlalu banyak file yang dikembalikan.
Dennis Nolte
4

Jika Anda berdiri diam di lorong-lorong Unix & Linux dan mendengarkan dengan seksama, Anda akan mendengar suara hantu, meratap sedih, "Bagaimana dengan nama file yang mengandung baris baru?"

ls -d *snp* | wc -l

atau, secara setara ,

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

akan menampilkan semua nama file yang berisi snp, masing-masing diikuti oleh baris baru, tetapi juga termasuk baris baru dalam nama file , dan kemudian menghitung jumlah baris dalam output. Jika ada file yang namanya

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

maka nama itu akan ditulis sebagai

foosnp
bar.tsv

yang, tentu saja, akan dihitung sebagai dua baris.

Ada beberapa alternatif yang lebih baik dalam setidaknya beberapa kasus:

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

yang menghitung garis yang berisi snp, jadi foosnp(\n)bar.tsvcontoh dari di atas hanya dihitung satu kali. Sedikit variasi dalam hal ini adalah

ls -f | grep -c snp

Dua perintah di atas berbeda karena:

  • Ini ls -fakan mencakup file yang namanya dimulai dengan .; yang printf … *tidak, kecuali dotglobopsi shell diatur.
  • printfadalah shell builtin; lsadalah perintah eksternal. Oleh karena itu, lsmungkin menggunakan sumber daya sedikit lebih.
  • Ketika shell memproses a *, ia mengurutkan nama file; ls -ftidak mengurutkan nama file. Oleh karena itu, lsmungkin menggunakan sumber daya sedikit lebih sedikit.

Tetapi mereka memiliki sesuatu yang sama: mereka berdua akan memberikan hasil yang salah di hadapan nama file yang mengandung baris baru dan memiliki snpkeduanya sebelum dan sesudah baris baru .

Lain:

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

Ini membuat variabel array shell yang mencantumkan semua nama file yang berisi snp, dan kemudian melaporkan jumlah elemen dalam array. Nama file diperlakukan sebagai string, bukan baris, jadi baris baru yang disematkan tidak menjadi masalah. Bisa dibayangkan bahwa pendekatan ini dapat memiliki masalah jika direktori sangat besar, karena daftar nama file harus disimpan dalam memori shell.

Lagi:

Sebelumnya, ketika kami mengatakan printf "%s\n" *snp*, printfperintah mengulang (menggunakan kembali) "%s\n"format string sekali untuk setiap argumen dalam perluasan *snp*. Di sini, kami membuat perubahan kecil dalam hal itu:

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

Ini akan mengulang (menggunakan kembali) "%.0s\n"format string sekali untuk setiap argumen dalam perluasan *snp*. Tetapi "%.0s"berarti untuk mencetak nol karakter pertama dari setiap string - yaitu, tidak ada. Ini printfperintah akan menampilkan hanya baris baru (yaitu, baris kosong) untuk setiap file yang berisi snpnamanya; dan kemudian wc -lakan menghitungnya. Dan, sekali lagi, Anda dapat memasukkan .file dengan pengaturan dotglob.

G-Man Mengatakan 'Reinstate Monica'
sumber
1

Abstrak:

Bekerja untuk file dengan nama "ganjil" (termasuk baris baru).

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

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

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

Deskripsi

Sebagai gumpalan sederhana akan cocok dengan setiap nama file dengan snpnamanya gampang echo *snp*saja sudah cukup untuk kasus ini, tetapi untuk benar-benar menunjukkan bahwa hanya ada tiga file yang cocok yang akan saya gunakan:

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

Satu-satunya masalah yang tersisa adalah untuk menghitung file. Ya, grep adalah solusi biasa, dan ya menghitung baris baru dengan wc -ljuga merupakan solusi biasa. Perhatikan bahwa grep -c(hitungan) benar-benar menghitung berapa kali suatu snpstring cocok, dan, jika satu nama file memiliki lebih dari satu snpstring dalam nama, hitungannya akan salah.

Kita bisa melakukan yang lebih baik.

Salah satu solusi sederhana adalah dengan mengatur argumen posisi:

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

Untuk menghindari mengubah argumen posisi kita dapat mengubah setiap argumen menjadi satu karakter dan mencetak panjang string yang dihasilkan (untuk sebagian besar shell):

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

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

Atau, dalam bash, untuk menghindari subkulit:

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

Daftar file

Daftar file (dari pertanyaan asli dengan satu dengan baris baru ditambahkan):

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' 

Itu akan memiliki file dengan satu baris baru di tengah:

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

Dan untuk menguji ekspansi glob:

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

Itu akan menambahkan tanda bintang, yang, jika tidak dikutip, akan diperluas ke seluruh daftar file.

NotAnUnixNazi
sumber
-1

katakanlah Anda ingin menghitung jumlah file html:

ls | grep ".html" | wc -l

jadi jika Anda menghitung kemunculan "snp":

ls | grep "snp" | wc -l
Daniel McGrath
sumber