2016-01-01 9 views

risposta

3

Process substitution fornisce un meccanismo attraverso il quale bash può generare una temporanea, il nome del file leggibile collegato ad un pezzo arbitraria di codice bash per voi:

./my_program -input <(while cat file_to_repeat; do :; done) 

Questo creerà un nome /dev/fd/NN in stile su sistemi operativi che lo supportano, o una named pipe altrimenti .

+0

funziona alla grande ora, grazie! – rogerdpack

1

Appare è possibile attraverso l'utilizzo di mkfifo (in questo modo permette un facile controllo, restartability, e file di grandi dimensioni)

$ mkfifo eternally_looping_filename # you can name this what you want. 

quindi scrivere a quella FIFO "looping" da un prompt di bash, es: creare script chiamato bash_write_eternal.sh:

while [ true ]; do 
    cat /path/to/file_want_repeated > ./eternally_looping_filename 
done 

run che in un terminale

$ ./bash_write_eternal.sh 

(si potrebbe fondo anche se si vuole riutilizzare lo stesso terminale)

poi in un altro terminale, eseguire il programma di input, come

$ ./my_program -input ./eternally_looping_filename 

o

$ cat ./eternally_looping_filename | ./my_program 

il programma sarà ora riceviamo un eterno input di quel file che ricopre continuamente. È anche possibile "mettere in pausa" il programma ricevente interrompendo il terminale che esegue lo script bash_write_eternal.sh (il suo input verrà sospeso fino a quando non si riprenderà lo script di scrittura fifo).

Un altro vantaggio è "riassumibile" tra le chiamate e anche se il tuo programma non sa come ricevere input da "stdin" può riceverlo da un nome di file qui.

+2

In primo luogo, il linguaggio è 'while true; do' o 'while:; do'. Secondo, non hai bisogno di una named pipe per questo. 'mentre:; fare gatto/percorso/a/file/a/essere/ripetuto; fatto | ./another-program' è sufficiente. Potrebbe essere necessario un '-input -' per il tuo altro programma, a seconda di come è codificato. – 4ae1e1

+0

BTW, se nella domanda hai indicato che il tuo programma ha accettato un parametro '-input', avresti ottenuto una risposta efficace molto più rapidamente. –

+0

'mentre gatto/percorso/su/file/per/essere/ripetuto; fare :; done' si chiuderebbe correttamente dopo che l'altro lato della FIFO è stato chiuso.(Come descritto in altri commenti, 'while [true]' è fuorviante, anche se volevi quel comportamento, usa 'while true'). –

3

Sì.

while [ true ]; do cat somefile; done | somecommand 
+2

Dovrebbe essere solo "while true;'. Non hai bisogno di '[]', questo è per testare le espressioni. – Barmar

+3

L'effetto è lo stesso, però. '[true]' succede perché '[l'argomento di' s è una stringa non vuota. '[falso]' funzionerebbe altrettanto bene, ma penso che tutti possano essere d'accordo sul fatto che sia inutilmente confuso :) – chepner

+0

L'unico disegno che ho con questo approccio (dopo averlo provato) è che se provi a inviare "stdin" a ' somecommand' (ad esempio, il tasto 'q' per uscire) a volte non lo riceve, il che, se necessario per interrompere con grazia quel comando, rende difficile l'uscita ... – rogerdpack

5

Il yes command, utilizzando il contenuto del file in quanto è argomento:

yes "$(<file)" | somecommand 
+3

Un effetto collaterale di questo approccio è che eventuali modifiche al file non * vengono * rilevate. Continuerà a ripetere i contenuti del file come erano al momento in cui è stato eseguito per la prima volta. Nel caso questo sia importante. – Ziffusion

+2

sfortunatamente, almeno in OS X, con file di input più grandi questo produce '/ usr/bin/yes: lista degli argomenti troppo lunga ' – rogerdpack

+0

... inoltre non funziona (tronca il contenuto) se quel file contiene NUL. –

0

Un ciclo while : ripete sempre:

while : 
do cat input.txt 
done | your-program 

Per usare una funzione di supporto:

repeat() while :; do cat "$1"; done 
repeat input.txt | your-program 
+0

ahh, ma non vogliamo veramente * per sempre *; vogliamo * fino a che 'your-program' non esca *. Ciò richiede che interrompiamo il ciclo dopo che 'cat' fallisce. –