3

For some reason when I try to specify a file name for \includegraphics in a loop, either using \foreach or using \clist, I get a file not found error. The error displays a valid path for the file, and if I use function parameter instead of trying to loop through a list it works right. There seems to be some issue with using loops and specifying files. How do I get this to generate usable file paths?

\documentclass{article}

\usepackage{graphicx}
\usepackage{pgffor}

\newcommand{\lmrf}[3]
{
    \begin{figure}
    \centering
    \foreach \f in {#1}
    {
         \includegraphics{./Figures/\f}
    }
    \caption{#2}
    \label{fig:#3}
    \end{figure}
}

\begin{document}

\lmrf{SURF1.png,SURF2.png}{(left) (right)}{rates}

\end{document}

This returns the error "! LaTeX Error: File `./Figures/SURF1.png' not found." ./Figures/SURF1.png is a file that is in that path. It works fine if I get rid of the loop.

This works:

\documentclass{article}

\usepackage{graphicx}

\newcommand{\lmrf}[3]
{
    \begin{figure}
    \centering
    \includegraphics{./Figures/#1}
    \caption{#2}
    \label{fig:#3}
    \end{figure}
}

\begin{document}

\lmrf{SURF1.png}{(left) (right)}{rates}

\end{document}

Update: Seems there's some underlying issue with resolving file names and loops. If I don't specify a path, it works. If I don't specify a file extension, it works. But, if a full path and file name including extension are specified it won't work.

Simply changing to:

\lmrf{SURF1,SURF2}{(left) (right) }{rates}

resulted in finding the files properly.

0
3

You're primary mistake is in the syntax of the \foreach group. It should be:

\foreach <var> in {<list>}
{<action>}

I used your earlier example:

\documentclass{article}
\usepackage{amsmath}
\usepackage{pgffor}
\usepackage{float}
\usepackage{graphicx}
\usepackage{mwe}

\newcommand{\lmrf}[3]
{
 \begin{figure}[H]
 \centering
 \foreach \f/\r in {#1}
  {%%
  \includegraphics[width=0.45\columnwidth,keepaspectratio=true,angle=\r]{\f}%%{./Figures/\f};
  }%%
 \caption{#2}
 \label{fig:#3}
 \end{figure}
}

\begin{document}

\lmrf{example-image-a/30,example-image-b}{Caption}{Figure}

\end{document}

enter image description here

I used your code:

 \foreach \f/\r in {#1}
  {%%
  \includegraphics[width=0.45\columnwidth,keepaspectratio=true,angle=\r]{./Figures/\f};%%
  }%%

and called it successfully with

\lmrf{restaurant/30,oak_tree/-10}{Caption}{Figure}

But

\lmrf{restaurant.png/30,oak_tree.png/-10}{Caption}{Figure}

I would suggest removing the png suffix:

enter image description here

2
  • That worked because the ./Figure/ part of the path was removed. It's not a compound statement being looped over, {} isn't needed. I'd like the figures in a static location.
    – Eric
    Sep 26 '18 at 20:15
  • @Eric I created the same sort of directory structure as you have and I get a successful run. The difference I have is that I don't use the png suffix as it appears you do. Remove the png and all should be good.
    – A.Ellett
    Sep 26 '18 at 20:46
1

The syntax

\foreach \f in {<list>} <code>;

only works in the context of a TikZ picture (and not even always).

The generally correct code is

\foreach \f in {<list>} {<code>}

On the other hand, I'm not sure that you gain that much with such code obfuscation. Typing

\begin{figure}[htp]
\centering

\includegraphics{./Figures/SURF1}%
\includegraphics{./Figures/SURF2}

\caption{(left) (right)}
\label{fig:rates}
\end{figure}

doesn't seem so burdensome. If you have several of these constructs, it *might be useful to have an abbreviation, but in that case the [H] option will most likely be of a hindrance, rather than help.

A reduced version:

\documentclass{article}

\usepackage{pgffor}

\newcommand{\insertfigures}[1]{%
  \foreach \f in {#1}{\includegraphics{./Figures/\f}}%
}

\begin{document}

\begin{figure}[htp]
\centering
\insertfigures{SURF1,SURF2}

\caption{(left) (right)}\label{rates}
\end{figure}

\end{document}

This keeps \caption and \label searchable.

A more flexible implementation with key-value syntax.

\documentclass{article}
\usepackage{graphicx}
\usepackage{xparse}

\ExplSyntaxOn
\keys_define:nn { eric/lmrf }
 {
  pos     .tl_set:N = \l_eric_lmrf_pos_tl,
  pos     .initial:n = htp,
  caption .tl_set:N = \l_eric_lmrf_caption_tl,
  label   .tl_set:N = \l_eric_lmrf_label_tl,
  path    .tl_set:N = \l_eric_lmrf_path_tl,
  o       .tl_set:N = \l_eric_lmrf_option_tl,
  f       .code:n =
   {
    \seq_put_right:Nn \l_eric_lmrf_images_seq { #1 }
    \seq_put_right:NV \l_eric_lmrf_options_seq \l_eric_lmrf_option_tl
   },
 }
\seq_new:N \l_eric_lmrf_images_seq
\seq_new:N \l_eric_lmrf_options_seq

\NewDocumentCommand{\lmrf}{m}
 {
  \use:x { \exp_not:N \begin{figure}[\l_eric_lmrf_pos_tl] }
  \keys_set:nn { eric/lmrf } { #1 }
  \centering
  \int_step_inline:nn { \seq_count:N \l_eric_lmrf_images_seq }
   {
    \use:x
     {
      \exp_not:N \includegraphics
       [ \seq_item:Nn \l_eric_lmrf_options_seq { ##1 } ]
       { \l_eric_lmrf_path_tl \seq_item:Nn \l_eric_lmrf_images_seq { ##1 } }
     }
   }
  \caption{\tl_use:N \l_eric_lmrf_caption_tl}
  \label{\tl_use:N \l_eric_lmrf_label_tl}
  \end{figure}
 }
\NewDocumentCommand{\lmrfsetup}{m}
 {
  \keys_set:nn { eric/lmrf } { #1 }
 }
\ExplSyntaxOff

%\lmfrsetup{./Figures/}

\begin{document}

\lmrf{
  caption={(left) (right)},
  label=rates,
%  path=./Figures/
  o = {width=3cm},
  f = example-image,
  f = example-image-a
}

\lmrf{
  caption={(left) (center) (right)},
  label=foo,
%  path=./Figures/
  o = {width=3cm},
  f = example-image,
  f = example-image-a,
  o = {width=2cm},
  f = example-image-b
}

\end{document}

The defined keys are caption, label, pos, path,oandf. The first two should be self-explanatory;pos(default valuehtp) is for the positioning argument tofigure`.

With o you can specify options to \includegraphics. Until countermanded by another o key, the option will be set for all the following images, as shown in the second example.

The path key is for specifying the path for the images. You can also specify it in the preamble with \lmfrsetup, say

\lmfrsetup{path=./Figures/}

as shown. In this case you don't need to specify the key in the \lmfr command. I commented out all calls just because I was lazy to make a directory structure.

enter image description here

1
  • This looks like it could be a very useful response. I'm trying to standardize the way graphics are displayed in a collaborative document using submissions by multiple authors.
    – Eric
    Sep 27 '18 at 14:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.