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.