Tale comando dipende dalla shell che genera 5000 argomenti e li passa a printfcui li ignora. Mentre può sembrare piuttosto veloce - ed è relativo ad alcune cose - la shell deve comunque generare tutte quelle stringhe come args (e delimitarle) e così via.
Oltre al fatto che gli H generati non possono essere stampati fino a quando la shell non passa per la prima volta a 5000, quel comando costa anche in memoria tutto ciò che serve per archiviare e delimitare gli argomenti di stringa numerici a printf più gli H. Proprio come puoi semplicemente fare:
printf %05000s|tr \ H
... che genera una stringa di 5000 spazi - che, almeno, di solito sono solo un singolo byte per e non costano nulla da delimitare perché non sono delimitati. Alcuni test indicano che anche per un minimo di 5000 byte il costo della forcella e del tubo richiesti trvale la pena anche in questo caso, e quasi sempre accade quando i numeri aumentano.
Mi sono imbattuto...
time bash -c 'printf H%.0s {1..5000}' >/dev/null
...e...
time bash -c 'printf %05000s|tr \ H' >/dev/null
Ciascuno circa 5 volte un pezzo (niente di scientifico qui - solo aneddotico) e la versione di espansione del controvento è stata in media di poco più di 0,02 secondi nel tempo totale di elaborazione, ma la trversione è arrivata a circa 0,02 secondi in totale - e la trversione ha battuto ogni volta. Non posso dire di essere sorpreso - {brace expansion}è un'utile funzione di stenografia interattiva della shell, ma di solito è una cosa piuttosto dispendiosa da fare per qualsiasi tipo di scripting. La forma comune:
for i in {[num]..[num]}; do ...
... quando ci pensate, in realtà sono due for loop: il primo è interno e implicito nel fatto che la shell deve eseguire un ciclo in qualche modo per generare quegli iteratori prima di salvarli tutti e iterarli nuovamente per il forloop. Queste cose di solito sono fatte meglio come:
iterator=$start
until [ "$((iterator+=interval))" -gt "$end" ]; do ...
... perché memorizzi solo pochissimi valori e li sovrascrivi mentre vai oltre a fare l'iterazione mentre generi gli iterabili.
Ad ogni modo, come il padding spaziale menzionato in precedenza, puoi anche usare printfper zeropad un numero arbitrario di cifre, ovviamente, come:
printf %05000d
Faccio entrambe le cose senza argomenti perché per ogni argomento specificato nella printfstringa di formato quando non viene trovato un argomento viene utilizzata la stringa null, che viene interpretata come zero per un argomento digit o una stringa vuota per una stringa.
Questo è l'altro (e - a mio avviso - più efficiente) della medaglia rispetto al comando nella domanda - mentre è possibile non ottenere nulla da qualcosa come si fa quando si printf %.0allungano le stringhe per ogni argomento, quindi è anche è possibile ottenere qualcosa dal nulla.
Ancora più veloce per grandi quantità di byte generati che puoi usare ddcome:
printf \\0| dd bs=64k conv=sync
... e l' argomento dddei file regolari seek=[num]può essere usato per un maggiore vantaggio. Puoi ottenere 64k newline anziché null se aggiungi ,unblock cbs=1a quanto sopra e da lì puoi iniettare stringhe arbitrarie per riga con pastee /dev/null- ma in tal caso, se è disponibile per te, puoi anche usare:
yes 'output string forever'
Ecco ddcomunque altri esempi:
dd bs=5000 seek=1 if=/dev/null of=./H.txt
... che crea (o tronca) un \0NULfile riempito nella directory corrente denominata H.txt di dimensione 5000 byte. ddcerca dritto all'offset e riempie NUL tutto dietro di esso.
<&1 dd bs=5000 conv=sync,noerror count=1 | tr \\0 H >./H.txt
... che crea un file con lo stesso nome e dimensione ma riempito con caratteri maiuscoli / minuscoli. Sfrutta ddil comportamento specifico di scrivere almeno un blocco null completo in caso di un errore di lettura quando vengono specificate noerrore le syncconversioni (e - senza count=- probabilmente andrebbero avanti più a lungo di quanto si possa desiderare) e reindirizzamenti intenzionali un descrittore di file scrivibile solo allo ddstdin.
tcshozsh,repeat 5000 printf Hè più facile da capire. Conperl:print "H" x 5000(notare che che{1..5000}è un operatore di zsh ispirato aperl's1..5000uno e poi copiato da ksh93 e bash)