2010-10-09 12 views
12

Estoy escribiendo una aplicación que actúa como un filtro: lee la entrada de un archivo (stdin), procesa y escribe la salida a otro archivo (stdout). El archivo de entrada se lee completamente antes de que la aplicación comience a escribir el archivo de salida.Usando el mismo archivo para stdin y stdout con redirección

Desde que estoy usando entrada y salida estándar, que se puede ejecutar es la siguiente:

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

Funciona bien, pero si trato de utilizar el mismo archivo como entrada y de salida (es decir: lee desde un archivo y escribir en el mismo archivo), así:

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

limpia file.txt antes de que el programa tiene la oportunidad de leerlo.

¿Hay alguna manera de que pueda hacer algo como esto en una línea de comandos en Unix?

Respuesta

13

El shell es lo que bloquea su archivo de salida, ya que está preparando la salida filehandles antes de ejecutar su programa. No hay forma de que su programa lea la entrada antes de que el shell anule el archivo en una sola línea de comandos.

Es necesario utilizar dos comandos, o bien mover o copiar el archivo antes de leerlo:

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

O de lo contrario la salida a una copia y luego reemplazar el original:

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

Si es posible No hagas eso, entonces necesitas pasar el nombre del archivo a tu programa, lo que abre el archivo en modo de lectura/escritura, y maneja todas las E/S internamente.

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

Para una solución de carácter puramente académico:

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

Posiblemente problemáticos efectos secundarios son:

  • ./myprog Si falla, se destruyan su entrada. (Naturalmente ...)
  • ./myprog se extiende desde un subnivel (Uso { ... ; } en lugar de (...) evitar.)
  • file.txt se convierte en un nuevo archivocon un nuevo nodo-i permisos y archivo.
  • Necesita +w permiso en el directorio de alojamiento file.txt.
+0

Extraño. ¿Por qué no funciona '$ (./myprog> file.txt) TheoYou

+0

Su ejemplo lo hace porque '> file.txt' trunca el contenido de file.txt y este es, de paso, el mismo archivo desde el que' file.txt' crea un * nuevo archivo * (inodo diferente en la misma ruta)) que está separado de lo que está leyendo ' antak

+0

Así que todo lo que tenemos que hacer es ejecutar el subconjunto nosotros mismos. Creo que sé la respuesta, pero todavía no estoy seguro de por qué ... – TheoYou

15

Hay una utilidad de esponja en moreutils paquete:

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

Para citar el manual:

Esponja lee la entrada estándar y lo escribe en el archivo especificado. A diferencia de una redirección de shell, la esponja absorbe toda su entrada antes de abrir el archivo de salida. Esto permite construir tuberías que leen y escriben en el mismo archivo.

+1

Por favor, elabore su respuesta. – Beppe

Cuestiones relacionadas