नाम पर विशिष्ट स्ट्रिंग के साथ निर्देशिका में फ़ाइलों की गणना करें?


12

मेरे पास निम्न फाइलें हैं:

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

मैं उन फाइलों की संख्या गिनना चाहता हूं snpजिनके नाम ( शब्द संवेदनशील) उनके नाम पर हैं। मैंने प्रयोग करने की कोशिश की

grep -a 'snp' | wc -l   

लेकिन तब मुझे एहसास हुआ कि grepफाइलों के भीतर खोज करता है। फ़ाइल नामों के माध्यम से स्कैन करने के लिए सही कमांड क्या है?


1
क्या आपने "गिनती फ़ाइलों" के लिए इस साइट को खोजने की कोशिश की है?
डॉन_क्रांति

जवाबों:


18

क्या आप snpफ़ाइल नामों में खोज करना चाहते हैं ? यह एक साधारण शेल ग्लोब (वाइल्डकार्ड) होगा, जिसका उपयोग इस तरह किया जाता है:

ls -dq *snp* | wc -l

-qयदि आपका संस्करण lsइसे नहीं पहचानता है तो ध्वज को छोड़ दें। यह "अजीब" वर्णों (नए सिरे सहित) वाले फ़ाइलनाम को संभालता है।


अगर मैं lsउनमें विशिष्ट पाठ के साथ फ़ाइल नामों को पुनः प्राप्त करने के लिए उपयोग कर सकता था तो निश्चित नहीं था। हालांकि यह काम किया, धन्यवाद।
लूसिया ओ

@LuciaO ने आपकी टिप्पणी को फिर से पढ़ा, ऐसा नहीं है lsकि फ़ाइल नामों से मेल खा रहा है , यह शेल है। lsपैटर्न से मेल खाती फ़ाइलों की सूची देखता है; यह स्वयं पैटर्न नहीं देखता है।
रोइमा

2
ध्यान दें कि यदि आपके पास बहुत सारी फाइलें लौट रही हैं तो यह काम नहीं कर सकता है।
डेनिस नोल्टे

4

यदि आप यूनिक्स और लिनक्स के हॉल में चुपचाप खड़े होते हैं और ध्यान से सुनते हैं, तो आप एक भूतिया आवाज़ सुनेंगे, जो कि आप के लिए नई कहानी होगी।

ls -d *snp* | wc -l

या, समकक्ष ,

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

वे सभी फ़ाइलनामों का उत्पादन करेंगे snp, जिनमें से प्रत्येक में एक नई पंक्ति है , लेकिन फ़ाइल नाम में कोई भी नया अंक शामिल है, और फिर आउटपुट में लाइनों की संख्या गिनें। अगर कोई फाइल है जिसका नाम है

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

फिर उस नाम के रूप में लिखा जाएगा

foosnp
bar.tsv

जो निश्चित रूप से, दो लाइनों के रूप में गिना जाएगा।

कुछ विकल्प हैं जो कम से कम कुछ मामलों में बेहतर करते हैं:

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

जो इसमें snpमौजूद लाइनों को गिनता है , इसलिए foosnp(\n)bar.tsvऊपर से उदाहरण केवल एक बार गिना जाता है। इस पर थोड़ी भिन्नता है

ls -f | grep -c snp

उपर्युक्त दोनों आज्ञाएँ इसमें भिन्न हैं:

  • उन ls -fफ़ाइलों में शामिल होंगे जिनके नाम के साथ शुरू होता है .; printf … *जब तक ऐसा नहीं करता, dotglobखोल विकल्प निर्धारित है।
  • printfएक शेल बिलिन है; lsएक बाहरी कमांड है। इसलिए, lsथोड़ा अधिक संसाधनों का उपयोग कर सकते हैं।
  • जब शेल प्रक्रिया करता है *, तो यह फ़ाइल नाम को सॉर्ट करता है; ls -fफ़ाइल नाम सॉर्ट नहीं करता है। इसलिए, lsथोड़ा कम संसाधनों का उपयोग कर सकते हैं।

लेकिन उनके पास सामान्य रूप से कुछ है: वे दोनों ऐसे नामपटनों की उपस्थिति में गलत परिणाम देंगे जिनमें नई रूपरेखा शामिल है और snpनई रेखा के पहले और बाद दोनों हैं

एक और:

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

यह सभी फ़ाइलनामों को सूचीबद्ध करने वाले शेल सरणी चर बनाता है snpऔर फिर सरणी में तत्वों की संख्या की रिपोर्ट करता है। फ़ाइलनामों को तार के रूप में माना जाता है, न कि रेखाओं के रूप में, इसलिए एम्बेडेड newlines कोई समस्या नहीं है। यह अनुमान योग्य है कि निर्देशिका के विशाल होने पर इस दृष्टिकोण में समस्या हो सकती है, क्योंकि फ़ाइल नाम की सूची को शेल मेमोरी में रखा जाना चाहिए।

अभी तक एक और:

इससे पहले, जब हमने कहा printf "%s\n" *snp*, printfकमांड ने "%s\n"विस्तार में प्रत्येक तर्क के लिए एक बार प्रारूप स्ट्रिंग (पुन: उपयोग) किया *snp*। यहाँ, हम उसमें एक छोटा सा बदलाव करते हैं:

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

यह "%.0s\n"विस्तार के प्रत्येक तर्क के लिए एक बार प्रारूप स्ट्रिंग (पुन: उपयोग) को दोहराएगा *snp*। लेकिन "%.0s"प्रत्येक स्ट्रिंग के पहले शून्य अक्षरों को प्रिंट करने का मतलब है - यानी, कुछ भी नहीं। यह printfकमांड प्रत्येक फ़ाइल के लिए केवल एक नई लाइन (यानी, एक रिक्त लाइन) का उत्पादन करेगा जिसमें snpउसका नाम शामिल है; और फिर wc -lउन्हें गिनेंगे। और, फिर से, आप .फ़ाइलों को सेटिंग में शामिल कर सकते हैं dotglob


1

सार:

"विषम" नामों (नई लाइनों सहित) के साथ फ़ाइलों के लिए काम करता है।

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

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

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

विवरण

जैसा कि एक साधारण ग्लोब हर फ़ाइल नाम के साथ मेल खाता है snp, इसके नाम पर एक साधारण echo *snp*इस मामले के लिए पर्याप्त हो सकता है, लेकिन वास्तव में यह दिखाने के लिए कि मेरे द्वारा उपयोग की जाने वाली मिलान की केवल तीन फाइलें हैं:

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

केवल शेष समस्या फ़ाइलों की गणना करने के लिए है। हाँ, grep एक सामान्य समाधान है, और हाँ नई लाइनों की गिनती wc -lभी एक सामान्य समाधान है। ध्यान दें कि grep -c(गिनती) वास्तव में गिना जाता है कि snpस्ट्रिंग कितनी बार मेल खाता है, और, यदि एक फ़ाइल नाम में एक से अधिक snpस्ट्रिंग हैं, तो गिनती गलत होगी।

हम बेहतर कर सकते हैं।

एक सरल उपाय है कि स्थैतिक तर्क निर्धारित करें:

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

स्थिति संबंधी तर्कों को बदलने से बचने के लिए हम प्रत्येक तर्क को एक वर्ण में बदल सकते हैं और परिणामी स्ट्रिंग की लंबाई प्रिंट कर सकते हैं (अधिकांश गोले के लिए):

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

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

या, एक उपशमन से बचने के लिए बैश में:

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

फ़ाइल सूची

फ़ाइलों की सूची (मूल प्रश्न के साथ एक नई पंक्ति के साथ एक के साथ):

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' 

जिसमें बीच में एक नई पंक्ति के साथ एक फ़ाइल होगी:

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

और ग्लोब विस्तार का परीक्षण करने के लिए:

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

यह एक तारांकन जोड़ देगा, जो कि, यदि अयोग्य है, तो फ़ाइलों की पूरी सूची में विस्तारित हो जाएगा।


-1

मान लें कि आप HTML फ़ाइलों की संख्या गिनना चाहते हैं:

ls | grep ".html" | wc -l

इसलिए यदि आप "स्निप" की घटनाएँ गिन रहे हैं:

ls | grep "snp" | wc -l
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.