Se você ficar quieto nos corredores do Unix e Linux e ouça atentamente,
você vai ouvir uma voz fantasmagórica, lamentavelmente lamentando,
“E os nomes de arquivos que contêm novas linhas?”
ls -d *snp* | wc -l
ou, de forma equivalente ,
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 incluindo quaisquer novas linhas nos nomes de arquivos ,
e conte o número de linhas na saída.
Se houver um arquivo cujo nome é
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á contado como duas linhas.
Existem algumas alternativas que melhoram em pelo menos alguns casos:
printf "%s\n" * | grep -c snp
que conta as linhas que contêm snp
,
Portanto, o exemplo foosnp(\n)bar.tsv
acima conta apenas uma vez.
Uma ligeira variação disso é
ls -f | grep -c snp
Os dois comandos acima são diferentes:
- O
ls -f
incluirá arquivos cujos nomes começam com .
;
o printf … *
não, a menos que a opção dotglob
shell esteja definida.
-
printf
é um shell embutido; ls
é um comando externo.
Portanto, o ls
pode usar um pouco mais de recursos.
- Quando o shell processa um
*
, ele classifica os nomes dos arquivos;
ls -f
não classifica os nomes dos arquivos.
Portanto, o ls
pode usar um pouco menos recursos.
Mas eles têm algo em comum:
ambos darão resultados errados na presença de nomes de arquivos
que contêm nova linha e têm snp
antes e depois da nova linha .
Outro:
filenamelist=(*snp*)
echo ${#filenamelist[@]}
Isso cria uma variável de matriz de shell listando todos os nomes de arquivos que
contém snp
e, em seguida, informa o número de elementos na matriz.
Os nomes dos arquivos são tratados como seqüências de caracteres, não linhas,
novas linhas embutidas não são um problema.
É concebível que esta abordagem possa ter um problema
se o diretório é enorme,
porque a lista de nomes de arquivos deve ser mantida na memória do shell.
Ainda outro:
Anteriormente, quando dissemos printf "%s\n" *snp*
,
o comando printf
repetido (reutilizado) a string de formato "%s\n"
uma vez para cada argumento na expansão de *snp*
.
Aqui, fazemos uma pequena mudança nisso:
printf "%.0s\n" *snp* | wc -l
Isso repetirá (reutilizar) a string de formato "%.0s\n"
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 comando printf
gerará apenas uma nova linha (ou seja, uma linha em branco)
para cada arquivo que contenha snp
em seu nome;
e então wc -l
os contará.
E, novamente, você pode incluir os arquivos .
definindo dotglob
.