Contar arquivos no diretório com uma string específica no nome?


12

Eu tenho os seguintes arquivos:

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

Quero contar o número de arquivos que possuem a palavra snp(diferencia maiúsculas de minúsculas) em seu nome. Eu tentei usar

grep -a 'snp' | wc -l   

mas então percebi que greppesquisas dentro dos arquivos. Qual é o comando correto para verificar os nomes dos arquivos?


1
Você já tentou pesquisar neste site por "arquivos de contagem"?
— 3113 don_crissti

Respostas:


18

Você quer procurar snpnos nomes dos arquivos ? Isso seria um simples shell shell (curinga), usado assim:

ls -dq *snp* | wc -l

Omita a -qbandeira se sua versão lsnão a reconhecer. Ele lida com nomes de arquivos contendo caracteres "estranhos" (incluindo novas linhas).


Não tinha certeza se eu poderia usar lspara recuperar nomes de arquivos com texto específico. Isso funcionou, obrigado.
— Lucia O

@LuciaO relendo seu comentário, não lsé o que corresponde aos nomes dos arquivos, é o shell. lsvê uma lista de arquivos que correspondem ao padrão; ele não vê o próprio padrão.
— roaima

2
observe que isso pode não funcionar se você tiver muitos arquivos retornando.
— Dennis Nolte

4

Se você ficar quieto nos corredores do Unix e Linux e ouvir com atenção, ouvirá uma voz fantasmagórica, lamentando lamentavelmente: "E os nomes de arquivos que contêm novas linhas?"

ls -d *snp* | wc -l

ou, equivalentemente ,

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

produzirá todos os nomes de arquivos que contêm snp, cada um seguido por uma nova linha, mas também inclui novas linhas nos nomes de arquivos e, em seguida, contará o número de linhas na saída. Se houver um arquivo cujo nome seja

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

então esse nome será escrito como

foosnp
bar.tsv

que, é claro, serão contados como duas linhas.

Existem algumas alternativas que se saem melhor em pelo menos alguns casos:

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

que conta as linhas que contêm snp, portanto, o foosnp(\n)bar.tsvexemplo acima conta apenas uma vez. Uma pequena variação nisso é

ls -f | grep -c snp

Os dois comandos acima diferem nisso:

  • O ls -fincluirá arquivos cujos nomes começam com .; a printf … *não acontecer, a menos que o dotglobopção de shell está definida.
  • printfé um shell embutido; lsé um comando externo. Portanto, o lspode usar um pouco mais de recursos.
  • Quando o shell processa a *, classifica os nomes dos arquivos; ls -fnão classifica os nomes de arquivos. Portanto, o lspode usar um pouco menos de recursos.

Mas eles têm algo em comum: ambos darão resultados errados na presença de nomes de arquivos que contenham nova linha e terão snpantes e depois da nova linha .

Outro:

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

Isso cria uma variável de matriz do shell listando todos os nomes de arquivos que contêm snpe, em seguida, relata o número de elementos na matriz. Os nomes de arquivos são tratados como seqüências de caracteres, não como linhas, portanto, novas linhas incorporadas não são um problema. É possível que essa abordagem possa ter um problema se o diretório for enorme, porque a lista de nomes de arquivos deve ser mantida na memória shell.

Ainda outra:

Anteriormente, quando dissemos printf "%s\n" *snp*, o printfcomando repetiu (reutilizou) a "%s\n"string de formato uma vez para cada argumento na expansão de *snp*. Aqui, fazemos uma pequena alteração nisso:

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

Isso repetirá (reutilizar) a "%.0s\n"cadeia de formatação uma vez para cada argumento na expansão de *snp*. Mas "%.0s"significa imprimir os primeiros zero caracteres de cada string - ou seja, nada. Este printfcomando produzirá apenas uma nova linha (ou seja, uma linha em branco) para cada arquivo que contém snpseu nome; e depois wc -lcontará eles. E, novamente, você pode incluir os .arquivos configurando dotglob.


1

Abstrato:

Funciona para arquivos com nomes "ímpares" (incluindo novas linhas).

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

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

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

Descrição

Como um glob simples corresponderá a cada nome de arquivo com snpum nome, um simples echo *snp*pode ser suficiente para este caso, mas para realmente mostrar que existem apenas três arquivos correspondentes, usarei:

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

O único problema restante é contar os arquivos. Sim, grep é uma solução usual e sim, contar novas linhas wc -ltambém é uma solução usual. Observe que grep -c(count) realmente conta quantas vezes uma snpstring é correspondida e, se um nome de arquivo tiver mais de uma snpstring no nome, a contagem estará incorreta.

Nós podemos fazer melhor.

Uma solução simples é definir os argumentos posicionais:

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

Para evitar alterar os argumentos posicionais, podemos transformar cada argumento em um caractere e imprimir o comprimento da string resultante (para a maioria dos shells):

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

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

Ou, no bash, para evitar um subshell:

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

Lista de arquivos

Lista de arquivos (da pergunta original com uma nova linha adicionada):

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' 

Isso terá um arquivo com uma nova linha no meio:

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

E para testar a expansão glob:

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

Isso adicionará um asterisco que, se não estiver entre aspas, será expandido para toda a lista de arquivos.


-1

digamos que você queira contar o número de arquivos html:

ls | grep ".html" | wc -l

então, se você está contando ocorrências de "snp":

ls | grep "snp" | wc -l
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.