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.