Entrada/salida
LaTeX usa la capacidad de escribir en un archivo y luego volver a leerlo para crear componentes de documentos como una tabla de contenido o un índice. También puedes leer un archivo que escribieron otros programas, o escribir un archivo para que otros lo lean. Te puedes comunicar con los usuarios a través de la terminal. Y puedes emitir instrucciones para el sistema operativo.

\openin y \openout
Sinopsis:

\openin number=filename

o:

\openout number=filename

Abre un archivo para leer material o para escribirlo. En la mayoría de los motores, el number debe estar entre 0 y 15, como en \openin3; en LuaLaTeX, number puede estar entre 0 y 127.
Aquí TeX abre el archivo presidents.tex para lectura.

\newread\presidentsfile
\openin\presidentsfile=presidentes
\typeout{presidentsfile es \el\presidentsfile}
\read\presidentsfile a\presidentline
\typeout{\presidentline}

El comando \newread asigna números de flujo de entrada desde 0 a 15 (también hay un \newwrite). El \presidentsfile es más memorable, pero bajo el capó sigue siendo un número; el primer \typeout da algo como ‘presidentsfile es 1’. Además, \newread realiza un seguimiento de la asignación de modo que si usas demasiados, obtendrás un error como ‘! No hay espacio para un nuevo \read’. El segundo \typeout da la primera línea del archivo, algo así como ‘1 Washington, George’.
Normalmente, TeX no intentará abrir el archivo hasta enviar la página siguiente. Para cambiar esto, usa \immediate\openin number=filename o \immediate\openout number=filename.
Cierra archivos con \closein number y \closeout number.
La forma en que LaTeX maneja los nombres de archivo varía entre las distribuciones e incluso puede variar entre las versiones de una distribución. Si el archivo no tiene una extensión entonces TeX agregará un .tex. Esto crea presidents.tex, escribe una línea y la cierra.

\newwrite\presidentsfile
\openout\presidentsfile=presidentes
\write\presidentsfile{1 Washington, George}
\closeout\presidentsfile

Pero los nombres de archivo con un punto pueden causar problemas: si TeX encuentra un filename de presidents.dat podría buscar primero presidents.dat.tex y posteriormente presidents.dat, o podría hacer lo contrario. La documentación de su distribución debe decir más, y si encuentras algo que funcione para ti, entonces eres bueno, pero para asegurar una portabilidad completa lo mejor es utilizar nombres de archivo que contiene solo las veintiséis letras ASCII (no distingue entre mayúsculas y minúsculas) y los diez dígitos, junto con el guión bajo y el guión, y en particular sin punto ni espacio.
Para \openin, si TeX no puede encontrar el archivo, entonces no da un error. Simplemente considera que la transmisión no está abierta (prueba esto con \ifeof; un recurso es el comando \InputIfFileExists, véase Comandos class y package). Si intentas usar el mismo número dos veces, LaTeX no te dará un error. Si intentas usar un número incorrecto y recibe un mensaje de error como ‘! Número incorrecto (16). <para leer de nuevo> = l.30 \openin16=test.jh’.

\read
Sinopsis:

\read number tomacro

Hace que el comando macro contenga la siguiente línea de entrada de texto que transmite number, como en \read5 to\data.
Esto abre el archivo email.tex para lectura, pone el contenido de la primera línea en el comando \email y luego cierra el archivo.

\newread\recipientfile
\openin\recipientfile=email
\read\recipientfile to\email
\typeout{Email address: \email}
\closein\recipientfile

Si number está fuera del rango de 0 a 15 o si no hay archivo de ese número abierto, o si el archivo ha finalizado, entonces \read tomará la entrada de la terminal (o saldrá si la interacción no está permitida, por ejemplo, \nonstopmode; véase modos de interacción). (Sin embargo, la forma natural en LaTeX de tomar entradas desde la terminal es \typein (véase \typein).
Para leer un archivo completo como fuente LaTeX adicional, usa \input (véase \input) o \include (véase \include e \includeonly).
Una razón común para querer leer de un archivo de datos es realizar combinaciones de correspondencia. CTAN tiene varios paquetes para eso; uno es datatool.

\typein
Sinopsis, una de:

\typein{prompt-msg}
\typein[cmd]{prompt-msg}

Imprime prompt-msg en la terminal y hace que LaTeX se detenga y espere a que escribas una línea de entrada. Esta línea de entrada termina cuando presiones la tecla de retorno.
Por ejemplo, este

Mientras  viva,   nunca  olvidaré  \typein{Ingresar  el   nombre  del
                                            estudiante:}

junto con esta interacción de la línea de comandos

Ingresa el nombre del estudiante:

\@typein=Aphra Behn

da la salida ‘... nunca olvides a Aphra Behn’.
La primera versión del comando, \typein{prompt-msg}, provoca la entrada que escribiste para ser procesada como si se hubiera incluido en el archivo de entrada en lugar del comando \typein
En la segunda versión del comando, el argumento opcional cmd debe ser un nombre de comando, es decir, debe comenzar con una barra invertida, \. Este nombre de comando se define o redefine para ser la entrada que escribiste. Por ejemplo, este

\typein[\student]{Ingresa el nombre del estudiante:}
\typeout{Recomendación para \student .}

da esta salida en la línea de comandos,

Ingresa el nombre del estudiante:

\student=John Dee
Recomendación para John Dee.

donde el usuario ha ingresado ‘John Dee.’

\typeout
Sinopsis:

\typeout{msg}

Imprime msg en la terminal y en el archivo log.
Este

\newcommand{\student}{John Dee}
\typeout{Recomendación para \student .}

genera ‘Recomendación para John Dee’. Como lo que pasa aquí con \student, comandos que se definen con \newcommand o \renewcommand (entre otros) se reemplazan por sus definiciones antes de ser impresos.
Las reglas habituales de LaTeX para tratar múltiples espacios como un solo espacio e ignorar los espacios después de un nombre de comando se aplica a msg. Utiliza el comando \space para obtener un solo espacio, independiente de los espacios circundantes. Usa ^^J para obtener una nueva línea. Obtener un carácter de porcentaje con \csname @percentchar\endcsname.
Este comando puede ser útil para una depuración simple, como aquí:

\newlength{\jhlength}
\setlength{\jhlength}{5pt}
\typeout{La longitud es \la\jhlength.}

produce en la línea de comandos ‘La longitud es 5.0pt’.

\write
Sinopsis:

\write number{string}

Escribe string en el archivo de registro, en la terminal o en un archivo abierto por \openout. Por ejemplo, \write6 escribe en texto corriente el número 6.
Si aparece lo siguiente en basefile.tex entonces se abre basefile.jh, escribe ‘Hello World!’ y una nueva línea y cierra ese archivo.

\newwrite\myfile
\immediate\openout\myfile=\jobname.jh  % \jobname is root file basename
...
\immediate\write\myfile{Hello world!}
...
\immediate\closeout\myfile

El \newwrite asigna un número de flujo, dándole un valor de nombre simbólico para hacer la vida más fácil, para que stream\newwrite\myfile\the\myfile produzca algo como ‘stream 3’. Entonces \openout asocia el número de flujo con el nombre de archivo dado. TeX finalmente ejecutó \write3 que pone la cadena en el archivo.
Por lo general, number está entre 0 y 15, porque normalmente los autores de LaTeX siguen el ejemplo anterior y se asigna el número por el sistema. Si number está fuera del rango de 0 a 15 o si no está asociado con un archivo abierto, LaTeX escribe string al archivo de registro. Si number es positivo entonces además LaTeX escribe string en la terminal.
Por lo tanto, test \write-1{Hello World!} pone ‘Hello World!’ seguido de una nueva línea en el archivo de registro. (Esto es lo que dice el \wlog el comando lo hace; véase \wlog). Y \write100{Hola Mundo!} pone lo mismo en el archivo de registro pero también pone ‘Hello World!’ seguido de una nueva línea en la salida del terminal. (Pero 16, 17 y 18 son especial como number; ve abajo).
En LuaTeX, en lugar de 16 flujos de salida, hay 256 (véase Motores TeX).
Usa \write\@auxout{string} para escribir en el actual .aux, que está asociado con el archivo raíz o con el archivo de inclusión actual; y usa \write\@mainaux{string} para escribir en el .aux principal. Estos nombres simbólicos están definidos por LaTeX.
De manera predeterminada LaTeX no escribe string a la derecha del arreglo correcto. Esto se debe a que, por ejemplo, puedes necesitar \write para guardar el número de página actual, pero cuando TeX encuentra un \write por lo general no sabe cuál es el número de página, ya que aún no ha hecho el salto de página. Entonces, usas \write en uno de tres contextos:

\immediate\write\@auxout{string}      %1
\write\@auxout{string}                %2
\protected@write\@auxout{}{string} %3

Con el primero, LaTeX escribe string en el archivo inmediatamente. Cualquier macro en string está completamente expandida (al igual que en \edef), por lo que para evitar la expansión debes usar \noexpand, toks, etc., excepto que debes usar # en lugar de ##).
Con el segundo, string se almacena en la lista actual de cosas (como un elemento TeX “whatsit”) y se mantiene hasta que se envía la página y así mismo las macros se contraen hasta \shipout. En \shipout, string está completamente expandido.
El tercer, \protected@write, es como el segundo excepto que puedes usar \protect para evitar la expansión. El primer argumento extra te permite insertar localmente definiciones adicionales para hacer más macros protegidas o tener alguna otra definición especial para escribir.
Como ejemplo simple de expansión con \write, string aquí contiene una secuencia de control \triplex que hemos definido como el texto ‘XYZ’:

\newwrite\jhfile
\openout\jhfile=test.jh
\newcommand{\triplex}{XYZ}
\write\jhfile{test \triplex test}

Esto da como resultado el archivo test.jh que contiene el texto ‘test XYZtest’ seguido de una nueva línea.
Los casos en los que number es 16, 17 o 18 son especiales. Porque el comportamiento de \write cuando number está fuera del rango de 0 a 15 descrito anteriormente, en Plain TeX \write16 y \write17 a veces se usaba para escribir en el archivo de registro y el terminal; sin embargo, en LaTeX, la forma natural de hacerlo es con \typeout (véase \typeout). El comando \write18 es aún más especial; los sistemas TeX modernos lo usan para dar órdenes al sistema operativo (véase \write18).
Normalmente, \write genera una sola línea. Puedes incluir una nueva línea con ^^J. Por lo tanto, esto produce dos líneas en el archivo de registro.:

\wlog{Las  líneas paralelas  tienen mucho  en común.^^JPero  nunca se
encuentran.}

Un caso común donde los autores necesitan escribir su propio archivo es para respuestas a ejercicios, u otra situación en la que quieras escribir textualmente, sin expandir las macros. CTAN tiene una serie de paquetes para esto; uno es answers.

\write y seguridad
La capacidad de escribir archivos plantea problemas de seguridad. Si compilaste un descargó el archivo LaTeX y sobrescribió su archivo de contraseña, entonces estarías justificadamente preocupado.
Por lo tanto, de manera predeterminada, los sistemas TeX solo te permiten abrir archivos para escritura que están en el directorio actual o directorio de salida, si se especifica (véase directorio de salida), o en un subdirectorio de aquellos. Entonces, este código

\newwrite\jhfile
\openout\jhfile=../test.jh

da un error como:

No escribir en ../test.jh (openout_any = p).
! No puedes escribir en el archivo `../test.jh'

Puedes obtener un error de este tipo cuando usas comandos como \include{../filename} porque LaTeX intentará abrir ../filename.aux. La solución más sencilla es poner los archivos incluidos en el mismo directorio que el archivo raíz, o en subdirectorios.

\message
Sinopsis:

\message{string}

Escribe string en el archivo de registro y en la terminal.
Por lo general, los autores de LaTeX usan \typeout (véase \typeout). Eso te permite usar \protect en cualquier comando frágil en string (véase \protect). Pero \typeout siempre inserta una nueva línea al final de string mientras que \message no lo hace, por lo que este último puede ser útil.
Con este cuerpo del documento de ejemplo.

antes\message{Uno Dos}\message{Tres}\message{Cuatro^^JI}
\message{declarar una guerra de pulgares.}Después

bajo algunas circunstancias (ve más abajo) LaTeX escribe lo siguiente para tanto la terminal como el archivo de registro.

Uno Dos Tres Cuatro
Declaro una guerra de pulgares.

El ^^J produce una nueva línea. Además, en el documento de salida, entre ‘before’ y ‘After’ será un solo espacio (del final de la línea que sigue a ‘I}’).
Si bien \message te permite tener más control sobre el formato, un inconveniente es que LaTeX puede estropear ese formato porque inserta saltos de línea dependiendo de lo que ya has escrito. Contrasta este cuerpo del documento, donde ‘Two’ se ha movido, al que se indica arriba.

antes de\message{Uno}\message{Dos Tres}\message{Cuatro^^JI}
\message{declara una guerra de pulgares.}Después

Esto puede suceder: cuando LaTeX envía los mensajes a la terminal, ahora el mensaje con ‘Uno’ es más corto y cabe al final de la línea de salida en la terminal, y entonces LaTeX rompe la línea entre él y ‘Dos Tres’. Ese salto de línea también aparece en el archivo de registro. Esta inserción de salto de línea puede depender, por ejemplo, de la longitud de los nombres completos de las rutas de los archivos incluidos. Por lo tanto, producir líneas de una manera que es portátil es difícil, probablemente requiera comenzando su mensaje al principio de una línea.

\wlog
Sinopsis:

\wlog{string}

Escribe string en el archivo de registro.

\wlog{¿Escuchaste sobre el matemático que odia los negativos?}
\wlog{No se detendrá ante nada para evitarlo.}

Por lo general, string aparece en una sola línea separada. Usa ^^J para insertar una nueva línea.

\wlog{Helvetica y Times Roman entran a un bar.}
\wlog{El barman dice,^^JNo servimos tu tipo.}

\write18
Sinopsis:

\write18{shell_command}

Emite un comando al shell del sistema operativo. El sistema operativo ejecuta el comando y la ejecución de LaTeX se bloquea hasta que acabe.
Esta secuencia (en Unix)

\usepackage{graphicx}  % en el preámbulo
  ...
\newcommand{\fignum}{1}
\immediate\write18{cd pix && asy figure\fignum}
\includegraphics{pix/figure\fignum.pdf}

ejecutará Asymptote (el programa asy) en pix/figure1.asy, para que luego el documento se pueda leer en el gráfico resultante (véase \includegraphics). Como cualquier \write, aquí LaTeX expande macros en shell_command para que \fignum sea reemplazado por ‘1’.
Otro ejemplo es que puedes ejecutar automáticamente BibTeX al inicio de cada ejecución de LaTeX (véase Usar BibTeX) incluyendo \immediate\write18{bibtex8 \jobname} como la primera línea del archivo. Ten en cuenta que \jobname se expande al nombre base del archivo raíz a menos que se pase la opción --jobname en la línea de comandos, en cuyo caso este es el argumento de la opción.
A veces es necesario realizar un proceso de varios pasos para obtener la información de eso que quieres. Esto insertará en la entrada una lista de todos los archivos PDF en el directorio actual (pero ve texosquery a continuación):

\immediate\write18{ls *.pdf > tmp.dat}
\input{tmp.dat}

El comportamiento estándar de cualquier \write es esperar hasta que una página sea enviada antes de expandir las macros o escribir en la secuencia (véase \write). Pero a veces quieres que se haga ahora. Para esto, usa \immediate\write18{shell_command}.
Hay problemas de seguridad obvios al permitir comandos del sistema dentro un archivo LaTeX. Si descargas un archivo de la red y contiene comandos para eliminar todos sus archivos, entonces no estarías satisfecho. La configuración estándar en las distribuciones modernas desactiva el acceso completo al intérprete de comandos. Lo puedes activar, si estás seguro de que los comandos del intérprete son seguros, compilando con latex --enable-write18 filename (véase Opciones de la línea de comandos). (La opción --shell-escape es un sinónimo, en TeX Live).
En lugar del acceso completo al intérprete, las distribuciones modernas por omisión una versión restringida que permite que funcionen algunos comandos, como los que ejecuta Metafont para generar fuentes que faltan, incluso si no usa la opción enable-write18. De manera predeterminada esta lista de commands permitidos es corto y presenta solo los comandos que están bajo el control de los mantenedores de la distribución (véase Opciones de la línea de comandos).
El texto shell_command siempre se pasa a /bin/sh en sistemas operativos similares a Unix y el intérprete de comandos de DOS cmd.exe en Windows. Cualquier intérprete diferente establecido por el usuario, y la variable de entorno SHELL se ignora.
Si lo que necesitas es información del sistema, como el nombre del sistema operativo, información local o contenido del directorio, echa un vistazo al paquete texosquery, que proporciona una forma de interfaz cómoda y segura para esto, a diferencia de los ejemplos anteriores que usan el \write18 simple \write18: https://ctan.org/pkg/texosquery.
LaTeX proporciona un paquete shellesc encima del comando primitivo \write18. Su propósito principal es proporcionar un comando \ShellEscape que funciona de manera idéntica en todos los motores TeX; LuaTeX intencionalmente no retuvo \write18 como una forma de invocar un comando del intérprete, por lo que se necesita algún código específico del motor. El paquete shellesc también proporciona un comando \DelayedShellEscape, ejecutado a la hora de \output, por la misma razón.