2010-10-09 15 views
12

Sto scrivendo un'applicazione che si comporta come un filtro: legge l'input da un file (stdin), elabora e scrive l'output in un altro file (stdout). Il file di input viene letto completamente prima che l'applicazione inizi a scrivere il file di output.Utilizzare lo stesso file per stdin e stdout con reindirizzamento

Dal momento che sto usando stdin e stdout, posso correre è come questo:

$ ./myprog <file1.txt >file2.txt 

Funziona benissimo, ma se cerco di utilizzare lo stesso file come input e output (cioè: leggere da un file e di scrittura per lo stesso file), in questo modo:

$ ./myprog <file.txt >file.txt 

pulisce file.txt prima che il programma ha la possibilità di leggerlo.

C'è un modo per fare qualcosa di simile in una riga di comando in Unix?

risposta

13

La shell è ciò che nasconde il file di output, poiché sta preparando i filehandle di output prima del in esecuzione del programma. Non c'è modo di fare in modo che il programma legga l'input prima che la shell copi il file in una singola riga di comando della shell.

È necessario utilizzare due comandi, uno spostamento o la copia del file prima di leggerlo:

mv file.txt filecopy.txt 
./myprog <filecopy.txt> file.txt 

Oppure l'output a una copia e quindi sostituire l'originale:

./myprog <file.txt> filecopy.txt 
mv filecopy.txt file.txt 

Se è possibile Fallo, quindi devi passare il nome del file al tuo programma, che apre il file in modalità lettura/scrittura e gestisce internamente tutto l'I/O.

./myprog file.txt     # reads and writes according to its own rules 
8

Per una soluzione di carattere puramente accademico:

$ (unlink file.txt && ./myprog >file.txt) <file.txt 

Forse problematici effetti collaterali sono:

  • Se ./myprog fallisce, si distrugge il vostro input. (Naturalmente ...)
  • ./myprog va da una subshell (Uso { ... ; } invece di (...) da evitare.)
  • file.txt diventa un nuovo filecon nuovi permessi inode e file.
  • È necessario il permesso +w sull'alloggiamento directory file.txt.
+0

Strano. Perché '$ (./myprog> file.txt) TheoYou

+0

L'esempio lo fa perché '> file.txt' tronca il contenuto di file.txt e questo è incidentalmente lo stesso file di cui' file.txt' crea un * nuovo file * (inode diverso sullo stesso percorso) che è separato da ciò che ' antak

+0

Quindi tutto ciò che dobbiamo fare è di eseguire noi stessi il sub-shell. Penso di conoscere la risposta, ma non sono ancora sicuro del perché ... – TheoYou

15

C'è un programma di utilità spugna in moreutils pacchetto:

./myprog < file.txt | sponge file.txt 

Per citare il manuale:

spugna legge standard input e scrive fuori per il file specificato. A differenza di un reindirizzamento della shell, la spugna assorbe tutti i suoi input prima di aprire il file di output. Ciò consente la costruzione di pipeline che leggono e scrivono nello stesso file.

+1

Per favore, elabora la tua risposta. – Beppe

Problemi correlati