"Archivo no encontrado" Cuando se utiliza el comando en lugar de texto sin formato

"Archivo no encontrado" Cuando se utiliza el comando en lugar de texto sin formato

Buen día,

Estoy intentando encontrar un método eficaz para acceder a archivos en una carpeta remota. He definido varios comandos para las rutas.

La línea 6 del siguiente código funciona e incluye el archivo correcto, mientras que la línea 8 dice "archivo no encontrado", pero ¿no deberían ser estas dos rutas exactamente iguales? ¿No puedo concatenar comandos como este?

1 \newcommand{\results}{../../code/data/results/}
2 \newcommand{\synthetic}{\results synthetic/}
3 \newcommand{\sine}[1]{sine_#1hz.pdf}
4
5
6 \includegraphics[width=.3\linewidth]{\synthetic sine_100hz.pdf}
7
8 \includegraphics[width=.3\linewidth]{\synthetic \sine{100}}

Quizás no estoy viendo algo obvio. Esta es la primera vez que trabajo con nombres de ruta en comandos. ¿Alguien sabe lo que me estoy perdiendo?

Salud

EDITAR: Este es un ejemplo de código completo:

\documentclass[]{article}
\usepackage{graphicx}
\begin{document}

\newcommand{\results}{../../code/waveletTest/data/results/}
\newcommand{\synthetic}{\results synthetic/}
\newcommand{\sine}[1]{sine_#1hz.pdf}

\includegraphics[width=.3\linewidth]{\synthetic sine_100hz.pdf}

%\includegraphics[width=.3\linewidth]{\synthetic \sine{100}}

\end{document}

Este código me muestra el archivo que quiero. Si vuelvo a comentar en la penúltima línea, aparece este error:

File `../../code/waveletTest/data/results/synthetic/sine_100hz.pdf' not found. ...width=.3\linewidth]{\synthetic \sine{100}}

Respuesta1

En mi sistema, en alguna etapa del procesamiento de su \includegraphicscomando, obtiene la secuencia:
\filename@parse{\synthetic\sine{100}}

\filename@parsees una rutina del núcleo LaTeX 2ε que dividirá su argumento en

  1. Ruta al archivo. La ruta al archivo se almacenará en la macro \filename@area.
  2. Nombre del archivo (sin extensión). El nombre del archivo (sin extensión) se almacenará en \filename@base.
  3. Extensión del nombre del archivo. La extensión del nombre del archivo se almacenará en \filename@ext. En caso de no haber extensión, \filename@extse deja igual a \relax.

¿Qué sucede?

En mi sistema \filename@parse, la sintaxis: se define de la siguiente manera:
\filename@parse{⟨file-path/filename-specification⟩}

> \filename@parse=macro:
#1->\let \filename@area \@empty \expandafter \filename@path #1/\\

Entonces \filename@parsese inicializa \filename@areapara igualar la macro \empty(la macro \emptysimplemente desaparece del flujo de tokens durante su expansión de nivel superior, sin procesar ningún argumento y entregando un texto de reemplazo que está vacío/que no consta de ningún token en absoluto) y llama la rutina \filename@pathdespués de "golpear" la primera ficha de la discusión con\expandafter una vezy añadiendo /\\al resultado. (En caso de que el argumento #1esté vacío, la barra diagonal adjunta /se verá afectada, \expandafterlo cual no es perjudicial ya que el token de carácter de barra diagonal explícito (del código cat 12 (otro)) no se puede expandir).

La rutina \filename@pathse explicará en breve. En este punto sólo hasta cierto punto:\filename@pathestá sangrado para procesar una secuencia de tokens de caracteres explícitos no expandiblesque forma una ruta de archivo/especificación de nombre de archivo ( #1), seguida por un token de carácter de barra diagonal explícito /del código de categoría 12 (otro) y un token de símbolo de control \\como delimitador/marcador para el final de la ruta de archivo/nombre de archivo -especificación.

Por lo tanto, "golpear \expandafteruna vez" se realiza en \filename@parsecaso de que el argumento para proporcionar la ruta de archivo/especificación de nombre de archivo no consista en una secuencia de tokens de caracteres explícitos no expandibles, sino que esté formado por un token macro cuyo nivel superior -expansion produce una secuencia de tokens de caracteres explícitos no expandibles.
Este "golpear \expandafteruna vez" implica que con cosas como \includegraphics, que usan internamente \filename@parse, puede proporcionar especificaciones de ruta de archivo/nombre de archivo solo en términos de secuencias de tokens donde presionar el primer token de la secuencia una \expandaftervez es suficiente para obtener la secuencia completa de tokens de caracteres explícitos no expandibles que forman la ruta de archivo/especificación de nombre de archivo.

Tenga en cuenta que en su escenario, un solo "golpe con \expandafter" en el primer token de la secuencia \synthetic \sine{100}no produce la ruta de archivo/especificación de nombre de archivo completa (completamente expandida) en términos de una secuencia de tokens de caracteres explícitos no expandibles, pero produce la secuencia \results synthetic/\sine{100}en la que es necesario realizar más trabajo de expansión.

Por lo tanto, la división/unión de los componentes (ruta al archivo, nombre del archivo sin extensión, extensión del nombre del archivo) no se realiza correctamente \filename@pathni por sus rutinas subyacentes.

La rutina \filename@path, a su vez, que "espera" que la ruta de archivo/especificación de nombre de archivo se proporcione en términos de una secuencia de tokens de caracteres explícitos no expandibles, sintaxis: ; es separador de carpeta/directorio y se define de la siguiente manera:
\filename@path ⟨file-path/filename-specification in terms of a sequence of non-expandable explicit character-tokens⟩/\\
/

> \filename@path=macro:
#1/#2\\->\ifx \\#2\\\def \reserved@a {\filename@simple #1.\\}\else \edef \filen
ame@area {\filename@area #1/}\def \reserved@a {\filename@path #2\\}\fi \reserve
d@a 

\filename@pathes un bucle recursivo que en cada iteración agrega el siguiente /segmento delimitado de la ruta de archivo/especificación de nombre de archivo a la macro \filename@areahasta llegar al último segmento que denota el nombre de archivo. El siguiente (y probablemente el último) segmento está en #1. Los segmentos que siguen al siguiente segmento están en #2. Así, el indicador del último segmento es el vacío de #2.
La prueba de vacío #2es: al llegar al último segmento de este tipo, que denota el nombre del archivo, se llama a la macro para verificar si ese último segmento/nombre de archivo contiene un punto ( ) y, por lo tanto, es necesario separar una extensión del nombre del archivo. . Si es necesario separar una extensión de nombre de archivo, esto se hace mediante la macro .
\ifx\\#2\\⟨tokens in case #2 is empty⟩\else⟨tokens in case #2 is not empty⟩\fi
\filename@simple.\filename@dot

Al llamar \filename@simplea la sintaxis: , en el último segmento delimitado que indica el nombre del archivo, la secuencia se agrega al último segmento. Por lo tanto, puede reunir un argumento delimitado por puntos y un argumento delimitado por puntos y, dependiendo del vacío de detectar, si se tomó un punto presente en el segmento o el punto adjunto como delimitador del argumento delimitado por puntos.
\filename@simple ⟨filename-specification in terms of a sequence of non-expandable explicit character-tokens⟩.\\
/.\\
\filename@simple#1\\#2#2

\filename@simplese define de la siguiente manera:

> \filename@simple=macro:
#1.#2\\->\ifx \\#2\\\let \filename@ext \relax \else \edef \filename@ext {\filen
ame@dot #2\\}\fi \edef \filename@base {#1}

Si el último segmento/nombre de archivo no contenía un punto, la .secuencia adjunta .\\se tomará como delimitador, #1mientras que el \\delimitado #2estará vacío. De lo contrario, el primer punto del último segmento se tomará como delimitador, #1mientras que el \\delimitador #2no estará vacío. Por lo tanto, el vacío de #2( \ifx\\#2\\...) se toma como indicador de si el último segmento forma un nombre de archivo sin extensión (separado por puntos) o forma un nombre de archivo que está separado de una extensión de archivo por un punto. Si #2está vacío, entonces \filename@ext" \let" es igual a \relax. De lo contrario, al definir \filename@extvía \edef, \filename@dotse aplica a las cosas detrás del primer punto para eliminar la secuencia adjunta .\\. En cualquier caso \filename@basese define expandir a las cosas antes del primer punto.

\filename@dotse define de la siguiente manera:

> \filename@dot=macro:
#1.\\->#1

Este \filename@parsemecanismo es bueno. Pero tiene algunas restricciones.

Por ejemplo, se supone que los nombres de archivos contienen como máximo un punto.

Por ejemplo, se supone que con nombres de archivos que contienen como máximo un punto, el punto separa el nombre del archivo (sin extensión) de la extensión del nombre del archivo que a su vez no está vacía. Los nombres de archivos que terminan en un punto (que son perfectamente "legales" en algunos sistemas de archivos) pueden causar problemas.

Por ejemplo, no se tienen en cuenta los caracteres especiales con códigos de categoría especiales. Por ejemplo, con especificaciones de ruta de archivo/nombre de archivo que contienen llaves, las llaves pueden estar desequilibradas o pueden eliminarse y/o pueden "enmascarar" puntos y barras para que no se tomen como delimitadores de argumentos delimitados. Cosas así causan problemas. Por ejemplo, las especificaciones de ruta de archivo/nombre de archivo que contienen hash pueden causar problemas cuando se trata de definir macros temporales como \reserved@alas macros que contienen los resultados de dividir la ruta de archivo/especificación de nombre de archivo.

Por ejemplo, se supone que un solo "impacto" de \expandafter/que desencadena un único paso de expansión (→de eso se trata el término "expansión de nivel superior") en el primer token del argumento de \filename@parsees suficiente para obtener la ruta completa del archivo. /especificación de nombre de archivo en términos de una secuencia de tokens de caracteres explícitos no expandibles. En su escenario, este no es el caso y, por lo tanto, los intentos de dividir cosas se realizan mientras \sineaún no están expandidos y, por lo tanto, el mecanismo aún no puede "ver" el punto que separa el nombre de archivo (sin extensión) de la extensión del nombre de archivo \filename@simple. Por lo tanto, en su escenario, el paquete gráficox "asume" erróneamente que no se especifica ninguna extensión de nombre de archivo. En caso de que el paquete graphicx "asuma" (sea correcta o errónea) que no se ha especificado una extensión de nombre de archivo, lo intenta con algunas extensiones predeterminadas.

Por ejemplo, en lugar de ../../code/waveletTest/data/results/synthetic/sine_100hz.pdfhacerlo, intenta con
../../code/waveletTest/data/results/synthetic/sine_100hz.pdf.pdf,
../../code/waveletTest/data/results/synthetic/sine_100hz.pdf.png,
../../code/waveletTest/data/results/synthetic/sine_100hz.pdf.jpg,
etc.

Es por eso que escribir "H⟨devolver⟩"cuando aparece el mensaje de error en la consola/pantalla:

I could not locate the file with any of these extensions:
.pdf,.png,.jpg,.mps,.jpeg,.jbig2,.jb2,.PDF,.PNG,.JPG,.JPEG,.JBIG2,.JB2,.eps
Try typing  <return>  to proceed.
If that doesn't work, type  X <return>  to quit.

La sugerencia de David Carlisle (quien escribió el paquete gráfico) de omitir la extensión del nombre de archivo .pdfapunta al hecho de que, aunque en este caso expandir las cosas antes de verificar la presencia de una extensión de nombre de archivo aún no se llevará a cabo de una manera que satisfaría las mentes puristas, la suposición del paquete gráficox de que no se especifica ninguna extensión de nombre de archivo será correcta y que, por lo tanto, el paquete gráficox prueba las extensiones predeterminadas de una manera que funciona: el paquete gráficox intenta con
../../code/waveletTest/data/results/synthetic/sine_100hz.pdf,
../../code/waveletTest/data/results/synthetic/sine_100hz.png,
../../code/waveletTest/data/results/synthetic/sine_100hz.jpg,
etc. .
El primero ya funciona.

Todas estas cosas se pueden solucionar cargando el paquete.archivo grffi:

\documentclass[]{article}
\usepackage{graphicx}
\usepackage{grffile}
\begin{document}

\newcommand{\results}{../../code/waveletTest/data/results/}
\newcommand{\synthetic}{\results synthetic/}
\newcommand{\sine}[1]{sine_#1hz.pdf}

%\includegraphics[width=.3\linewidth]{\synthetic sine_100hz.pdf}

\includegraphics[width=.3\linewidth]{\synthetic\sine{100}}

\end{document}

Por cierto:

En su caso muy especial, puede engañar al \filename@parsemecanismo para que corte la extensión del nombre de archivo correctamente agregando \expandafter:

\documentclass[]{article}
\usepackage{graphicx}
\begin{document}

\newcommand{\results}{../../code/waveletTest/data/results/}
\newcommand{\synthetic}{\results synthetic/}
\newcommand{\sine}[1]{sine_#1hz.pdf}

%\includegraphics[width=.3\linewidth]{\synthetic sine_100hz.pdf}

\includegraphics[width=.3\linewidth]{\expandafter\synthetic\sine{100}}

\end{document}

Al menos en mi sistema esto funciona.

Tenga en cuenta que esto divide la extensión del nombre del archivo correctamentepero que esto no separa correctamente la ruta del archivo del nombre del archivo.
La ruta del archivo se considerará vacía.
La secuencia \synthetic sine_100hzse tomará para el nombre del archivo.
Parece que esto no importa.

Pero \filename@parsees una macro del núcleo LaTeX 2ε. Y ha habido muchos cambios e innovaciones en el kernel LaTeX 2ε en el pasado reciente. Probablemente el \filename@parsede su sistema no funcione como lo hace en el mío.

Supongo que "presionar el primer token del argumento \expandafteruna vez para obtener de la expansión de nivel superior de una macro las especificaciones de ruta de archivo/nombre de archivo en términos de tokens de caracteres explícitos no expandibles" no se eliminará de \filename@parse.
Por lo tanto, puede aplicar algunos \romannumeraltrucos de expansión que necesitan un paso \expandafterpara entregar la ruta de archivo/especificación de nombre de archivo:

\documentclass[]{article}
\usepackage{graphicx}
\begin{document}

\newcommand{\results}{../../code/waveletTest/data/results/}
\newcommand{\synthetic}{\results synthetic/}
\newcommand{\sine}[1]{sine_#1hz.pdf}

%\includegraphics[width=.3\linewidth]{\synthetic sine_100hz.pdf}

\includegraphics[width=.3\linewidth]{\romannumeral0\expandafter\synthetic\sine{100}}

\end{document}

¿Qué pasa aquí?

\filename@parseEl \expandaferde "golpea" \romannumeral.
Luego \romannumeral-desencadenó la recopilación de un TeX-⟨número⟩-la cantidad está en progreso:

%\romannumeral-triggered gathering of a TeX-number-quantity is in progress:
0\expandafter\synthetic\sine{100}

Ahora LaTeX encuentra el dígito 0y lo descarta.
Ahora el proceso de reunir un TeX-⟨número⟩-la cantidad se convierte en el proceso de reunir más dígitos o algo que termine de reunir el TeX-⟨número⟩-cantidad:

%\romannumeral-triggered gathering of more digits is in progress; digit "0" found.
\expandafter\synthetic\sine{100}

Ahora LaTeX se expande \expandafter. El resultado de expandirse \expandafteres expandirse \sine:

%\romannumeral-triggered gathering of more digits is in progress; digit "0" found.
\synthetic sine_100hz.pdf

Ahora LaTeX se expande \synthetic.

%\romannumeral-triggered gathering of more digits is in progress; digit "0" found.
\results synthetic/sine_100hz.pdf

Ahora LaTeX se expande \results.

%\romannumeral-triggered gathering of more digits is in progress; digit "0" found.
../../code/waveletTest/data/results/synthetic/sine_100hz.pdf

Ahora LaTeX encuentra un punto. Ese punto no es un dígito. A diferencia de una ficha espacial, no se descarta. Como una ficha espacial, finaliza \romannumeralla reunión activada de (componentes de) TeX.⟨número⟩-cantidades. Por lo tanto, LaTeX solo encontró el dígito/número, 0mientras que 0 no es un número positivo. Con números no positivos, \romannumeralsilenciosamente no devuelve ningún token:

%\romannumeral done.
../../code/waveletTest/data/results/synthetic/sine_100hz.pdf

información relacionada