Mam następujące pliki:
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
Chcę policzyć liczbę plików, których nazwy zawierają słowo snp
(z rozróżnieniem wielkich i małych liter). Próbowałem użyć
grep -a 'snp' | wc -l
ale potem zdałem sobie sprawę, że grep
wyszukiwanie w plikach. Jakie jest prawidłowe polecenie do skanowania nazw plików?
Odpowiedzi:
Czy masz na myśli wyszukiwanie
snp
w nazwach plików ? Byłby to prosty glob globu powłoki (symbol wieloznaczny), używany w następujący sposób:Pomiń
-q
flagę, jeśli Twoja wersjals
go nie rozpoznaje. Obsługuje nazwy plików zawierające „dziwne” znaki (w tym znaki nowej linii).źródło
ls
do odzyskania nazw plików z określonym tekstem. To zadziałało, dzięki.ls
pasuje do nazw plików, to jest powłoka.ls
widzi listę plików pasujących do wzorca; to jest nie widzieć samego wzorca.Jeśli stoisz cicho na korytarzach Uniksa i Linuksa i słuchasz uważnie, usłyszysz upiorny głos, żałośnie lamentujący: „A co z nazwami plików, które zawierają nowe linie?”
lub, równoważnie ,
wypisze wszystkie nazwy plików, które zawierają
snp
, po których następuje nowa linia, ale także uwzględni wszystkie nowe linie w nazwach plików , a następnie policzy liczbę linii w danych wyjściowych. Jeśli istnieje plik o nazwief o o s n p \n b a r . t s v
wtedy ta nazwa zostanie zapisana jako
które oczywiście będą liczone jako dwie linie.
Istnieje kilka alternatyw, które działają lepiej przynajmniej w niektórych przypadkach:
która liczy linie, które zawierają
snp
, więcfoosnp(\n)bar.tsv
przykład z powyższego liczy się tylko raz. Jest to niewielka zmianaDwa powyższe polecenia różnią się tym, że:
ls -f
Będzie zawierać pliki, których nazwy zaczynają się.
;printf … *
nie, chyba żedotglob
opcja powłoki jest ustawiona.printf
jest wbudowaną powłoką;ls
to polecenie zewnętrzne. Dlategols
mogą zużywać nieco więcej zasobów.*
, sortuje nazwy plików;ls -f
nie sortuje nazw plików. Dlategols
mogą zużywać nieco mniej zasobów.Ale mają coś wspólnego: oba dadzą złe wyniki w obecności nazw plików zawierających znak nowej linii, które mają
snp
zarówno przed, jak i po nowej linii .Inne:
Spowoduje to utworzenie zmiennej tablicowej powłoki zawierającej wszystkie nazwy plików, które zawierają
snp
, a następnie zgłasza liczbę elementów w tablicy. Nazwy plików są traktowane jako ciągi znaków, a nie wiersze, więc osadzone znaki nowej linii nie stanowią problemu. Można sobie wyobrazić, że takie podejście może mieć problem, jeśli katalog jest ogromny, ponieważ lista nazw plików musi być przechowywana w pamięci powłoki.Jeszcze inny:
Wcześniej, kiedy powiedzieliśmy
printf "%s\n" *snp*
,printf
polecenie powtórzyło (ponownie wykorzystało)"%s\n"
ciąg formatu raz dla każdego argumentu w rozszerzeniu*snp*
. Tutaj dokonujemy niewielkiej zmiany w tym:Spowoduje to powtórzenie (ponowne użycie) ciągu
"%.0s\n"
formatu raz dla każdego argumentu w rozszerzeniu*snp*
. Ale"%.0s"
oznacza wydrukowanie pierwszych zerowych znaków każdego łańcucha - tzn. Nic. Toprintf
polecenie wyświetli tylko nowy wiersz (tj. Pusty wiersz) dla każdego pliku, który zawierasnp
w nazwie; i wtedywc -l
je policzą. I znowu możesz dołączyć.
pliki, ustawiającdotglob
.źródło
Abstrakcyjny:
Działa dla plików o „nieparzystych” nazwach (w tym nowych wierszach).
Opis
Ponieważ prosty glob pasuje do każdej nazwy pliku z
snp
nazwą, prostyecho *snp*
może być wystarczający w tym przypadku, ale aby naprawdę pokazać, że będą tylko trzy pasujące pliki, których użyję:Pozostaje tylko zliczyć pliki. Tak, grep jest zwykłym rozwiązaniem, i tak, liczenie nowych linii
wc -l
jest również zwykłym rozwiązaniem. Zauważ, żegrep -c
(liczba) naprawdę liczy, ile razysnp
dopasowany jest ciąg, a jeśli jedna nazwa pliku ma więcej niż jedensnp
ciąg w nazwie, liczba będzie niepoprawna.Możemy zrobić lepiej.
Jednym prostym rozwiązaniem jest ustawienie argumentów pozycyjnych:
Aby uniknąć zmiany argumentów pozycyjnych, możemy przekształcić każdy argument na jeden znak i wydrukować długość wynikowego łańcucha (dla większości powłok):
Lub, w skrócie, aby uniknąć podpowłoki:
Lista plików
Lista plików (z pierwotnego pytania z jednym z dodanym znakiem nowej linii):
To będzie miało plik z jedną nową linią pośrodku:
f o o s n p \n b a r . t s v
Aby przetestować globalną ekspansję:
To doda gwiazdkę, która, jeśli nie będzie cytowana, rozwinie się do całej listy plików.
źródło
powiedzmy, że chcesz policzyć liczbę plików HTML:
więc jeśli liczysz wystąpienia „snp”:
źródło