
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 \includegraphics
comando, obtiene la secuencia:
\filename@parse{\synthetic\sine{100}}
\filename@parse
es una rutina del núcleo LaTeX 2ε que dividirá su argumento en
- Ruta al archivo. La ruta al archivo se almacenará en la macro
\filename@area
. - Nombre del archivo (sin extensión). El nombre del archivo (sin extensión) se almacenará en
\filename@base
. - 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@ext
se 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@parse
se inicializa \filename@area
para igualar la macro \empty
(la macro \empty
simplemente 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@path
después de "golpear" la primera ficha de la discusión con\expandafter
una vezy añadiendo /\\
al resultado. (En caso de que el argumento #1
esté vacío, la barra diagonal adjunta /
se verá afectada, \expandafter
lo 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@path
se explicará en breve. En este punto sólo hasta cierto punto:\filename@path
está 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 \expandafter
una vez" se realiza en \filename@parse
caso 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 \expandafter
una 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 \expandafter
vez 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@path
ni 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@path
es 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@area
hasta 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 #2
es: 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@simple
a 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@simple
se 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, #1
mientras que el \\
delimitado #2
estará vacío. De lo contrario, el primer punto del último segmento se tomará como delimitador, #1
mientras que el \\
delimitador #2
no 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 #2
está vacío, entonces \filename@ext
" \let
" es igual a \relax
. De lo contrario, al definir \filename@ext
vía \edef
, \filename@dot
se aplica a las cosas detrás del primer punto para eliminar la secuencia adjunta .\\
. En cualquier caso \filename@base
se define expandir a las cosas antes del primer punto.
\filename@dot
se define de la siguiente manera:
> \filename@dot=macro:
#1.\\->#1
Este \filename@parse
mecanismo 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@a
las 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@parse
es 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 \sine
aú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.pdf
hacerlo, 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 .pdf
apunta 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@parse
mecanismo 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_100hz
se tomará para el nombre del archivo.
Parece que esto no importa.
Pero \filename@parse
es 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@parse
de su sistema no funcione como lo hace en el mío.
Supongo que "presionar el primer token del argumento \expandafter
una 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 \romannumeral
trucos de expansión que necesitan un paso \expandafter
para 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@parse
El \expandafer
de "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 0
y 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 \expandafter
es 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 \romannumeral
la reunión activada de (componentes de) TeX.⟨número⟩-cantidades. Por lo tanto, LaTeX solo encontró el dígito/número, 0
mientras que 0 no es un número positivo. Con números no positivos, \romannumeral
silenciosamente no devuelve ningún token:
%\romannumeral done.
../../code/waveletTest/data/results/synthetic/sine_100hz.pdf