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 .