Se ti trovi in silenzio nei corridoi di Unix e Linux e ascolti attentamente, sentirai una voce spettrale, che geme pietosamente, "E i nomi di file che contengono nuove righe?"
ls -d *snp* | wc -l
o, equivalentemente ,
printf "%s\n" *snp* | wc -l
produrrà tutti i nomi dei file che contengono snp, ciascuno seguito da una nuova riga,
ma includendo anche le eventuali nuove righe nei nomi dei file , quindi conterà il numero di righe nell'output. Se esiste un file il cui nome è
f o o
s n p \n
b a r
. t s v
allora quel nome sarà scritto come
foosnp
bar.tsv
che, ovviamente, verranno conteggiati come due righe.
Ci sono alcune alternative che fanno meglio in almeno alcuni casi:
printf "%s\n" * | grep -c snp
che conta le righe che contengono snp, quindi l' foosnp(\n)bar.tsvesempio di cui sopra conta solo una volta. Una leggera variazione su questo è
ls -f | grep -c snp
I due comandi precedenti differiscono in quanto:
- La
ls -fincluderà i file i cui nomi iniziano con .; il printf … *non fa a meno che l' dotglobopzione di shell è impostata.
printfè una shell incorporata; lsè un comando esterno. Pertanto, lspotrebbero utilizzare leggermente più risorse.
- Quando la shell elabora a
*, ordina i nomi dei file;
ls -fnon ordina i nomi dei file. Pertanto, lspotrebbe utilizzare leggermente meno risorse.
Ma hanno qualcosa in comune: entrambi daranno risultati sbagliati in presenza di nomi di file che contengono newline e avranno snpsia prima che dopo la nuova riga .
Un altro:
filenamelist=(*snp*)
echo ${#filenamelist[@]}
Questo crea una variabile di array di shell che elenca tutti i nomi di file che contengono snpe quindi riporta il numero di elementi nell'array. I nomi dei file sono trattati come stringhe, non linee, quindi le nuove righe incorporate non rappresentano un problema. È ipotizzabile che questo approccio possa avere un problema se la directory è enorme, perché l'elenco dei nomi dei file deve essere conservato nella memoria della shell.
Ancora un altro:
In precedenza, quando abbiamo detto printf "%s\n" *snp*, il printfcomando ha ripetuto (riutilizzato) la "%s\n"stringa di formato una volta per ogni argomento nell'espansione di *snp*. Qui, facciamo un piccolo cambiamento in questo:
printf "%.0s\n" *snp* | wc -l
Questo ripeterà (riutilizzerà) la "%.0s\n"stringa di formato una volta per ogni argomento nell'espansione di *snp*. Ma "%.0s"significa stampare i primi zero caratteri di ogni stringa, ovvero niente. Questo printfcomando produrrà solo una nuova riga (cioè una riga vuota) per ogni file che contiene snpnel suo nome; e poi wc -lli conterà. E, ancora una volta, puoi includere i .file impostando dotglob.