This problem is driving me nuts. I'd like to change the includegraphics path depending on some conditions. It seems simple, right?

I already read the answers to this question: Passing image path to \includegraphics using a macro, but I was unable to solve my issue. I learned that for \includegraphics the following must be true:

Thanks David Carlisle -> Incorrect Statement: From my understanding, my code only requires one level of expansion, but is still not working.

Is this a rare time when I need to use \DeclareExpandableDocumentCommand for \qikpicpath?


A prerequisite is having a jpg file on directory above the tex file called test_pic.jpg. I commended out the problematic code.


\ExplSyntaxOn % https://tex.stackexchange.com/a/275552/13552
\tl_new:N \g_qik_pic_class_tl % allocate a (global) variable
\tl_gset:Nn \g_qik_class_tl { I } % initialize the value
\NewDocumentCommand{\qikpicclass}{} % define a user level command for printing the value
    \tl_use:N \g_qik_class_tl
\NewDocumentCommand{\qiksetpicclass}{m} % define a user level command for changing the value
    \tl_gset:Nn \g_qik_class_tl { #1 }
    \tl_if_eq:VnTF \g_qik_class_tl { I }
        { \qikrootdirectory~test_pic.jpg } % true
        { \qikrootdirectory~test_pic.jpg } % false
\cs_generate_variant:Nn \tl_if_eq:nnTF { V }

\qikpicpath % Visually inspect expanded text.

\includegraphics[width=\textwidth]{\qikrootdirectory test_pic.jpg}% Works

%\includegraphics[width=\textwidth]{\qikpicpath}% Expansion Problem

\tikz \node (pic) {\includegraphics[width=\textwidth]{../test_pic.jpg}};% Works

%\tikz \node (pic) {\includegraphics[width=\textwidth]{\qikpicpath}};% Expansion Problem Related to Above

  • 3
    No ~ space before test_pic!
    – egreg
    Oct 29, 2015 at 15:33
  • @egreg I am removed both ~ spaces, but my output after uncommenting the first commented out line is ! You can't use `the letter I' after \the. <argument> Oct 29, 2015 at 15:54
  • @egreg I should also note that I use a space in that location in LaTeX2e code. Oct 29, 2015 at 16:08
  • it isn't clear what problem you are trying to solve, it is usually best not to have a path anyway but here since the file extension is not hidden in the macro the comments about expansion in the referenced question do not apply at all. \def\qikrootdirectory{../} should work if ../ works (security settings in texmf.cnf might prevent reading files in a path starting ../) Oct 29, 2015 at 16:50
  • @DavidCarlisle Haha I suspected that my understanding was completely off. You just confirmed it. So the expansion takes this course: \includegraphics>\qikpicpath>\tl_if_eq:VnTF \g_qik_class_tl { I }>\jkorootdirectory? Is that right? How is it not clear what problem I am trying to solve? The path is most definitely required in my case. The entire SVN system depends on paths. Oct 29, 2015 at 16:56

2 Answers 2


This could be a case where \DeclareExpandableDocumentCommand turns out to be useful, but it's simpler to use a different approach.

Let's say you have the same images in color and b/w versions, in two different folders, say ./colorimages and ./bwimages. Your purpose is to load pictures from one folder or another in case you compile your PDF for viewing or printing.

Let's also say that the images have consistent names like color-image1.jpg and bw-image1.jpg, so you want to do


and this will load the right image, either color or b/w, just with one switch to be set in the preamble.


    \g_macmadness_folder_tl/ % the folder
    \g_macmadness_prefix_tl % the prefix

  \str_case:nn { #1 }
      \tl_gset:Nn \g_macmadness_folder_tl { ./colorimages }
      \tl_gset:Nn \g_macmadness_prefix_tl { color- }
      \tl_gset:Nn \g_macmadness_folder_tl { ./bwimages }
      \tl_gset:Nn \g_macmadness_prefix_tl { bw- }

\tl_new:N \g_macmadness_folder_tl
\tl_new:N \g_macmadness_prefix_tl


Now you can state in the preamble




and call, in the document, \mmincludegraphics as stated before.

  • Hm interesting approach. My situation is possibly easier in that all shared images are in a common location. I will need to consider whether introducing a new \mmincludegraphics command just for one graphic is a wise option. Another less clean (duplicate code) approach I've considered is putting the \includegraphics command within conditional logic and hardcoding the image filenames in each condition. One complication: I would have to be able to access the optional parameters [width=,height=] of \includegraphics. Oct 29, 2015 at 18:57
  • Sorry, but I don't understand: all the work is for a single image?
    – egreg
    Oct 29, 2015 at 19:04
  • No, I mistakenly wrote "one graphic". I meant one graphic case. e.g. img-label-with-cert.jpg and img-label.jpg are in a common folder above the tex file's dir, but their names could be anything (but likely similar). On the contrary, all the work is for potentially many images. As this project is for a very expensive product, I try to only use scalable options. Oct 29, 2015 at 19:12
  • 1
    @macmadness86 It doesn't work like this: please, present your real problem with all specifications. The previous question had no image; this one has one image; the comment tells that there is one, but it can be many. I can't follow you.
    – egreg
    Oct 29, 2015 at 19:16
  • 1
    @macmadness86 If I use \str_if_eq:VnTF instead of \tl_if_eq:VnTF (no variant generation is necessary and \DeclareExpandableDocumentCommand` for \qikpicpath, it works. When \includegraphics processes the file name, it performs full expansion.
    – egreg
    Oct 30, 2015 at 9:41

If you add


Then TeX traces the expansion steps of this macro:

\qikpicpath ->\tl_if_eq:VnTF \g_qik_class_tl {I}{\qikrootdirectory test_pic.jpg
}{\qikrootdirectory test_pic.jpg}

\tl_if_eq:VnTF ->\exp_args:NV \tl_if_eq:nnTF 

\exp_args:NV #1#2->\exp_after:wN #1\exp_after:wN {\exp:w \__exp_eval_register:N

\__exp_eval_register:N #1->\exp_after:wN \if_meaning:w \exp_not:N #1#1\if_meani
ng:w \scan_stop: #1\__exp_eval_error_msg:w \fi: \else: \exp_after:wN \use_i_ii:
nnn \fi: \exp_after:wN \exp_end: \tex_the:D #1

\use_i_ii:nnn #1#2#3->#1#2

\g_qik_class_tl ->I

\tl_if_eq:nnTF #1#2->\group_begin: \tl_set:Nn \l__tl_internal_a_tl {#1}\tl_set:
Nn \l__tl_internal_b_tl {#2}\if_meaning:w \l__tl_internal_a_tl \l__tl_internal_
b_tl \group_end: \prg_return_true: \else: \group_end: \prg_return_false: \fi: \

\tl_set:Nn #1#2->\cs_set_nopar:Npx #1{\exp_not:n {#2}}

\tl_set:Nn #1#2->\cs_set_nopar:Npx #1{\exp_not:n {#2}}

\prg_return_true: ->\exp_after:wN \use_i:nn \exp:w 

\use_i:nn #1#2->#1
#1<-\qikrootdirectory test_pic.jpg
#2<-\qikrootdirectory test_pic.jpg

\qikrootdirectory ->../

Counting -> shows that it takes twelve expansions to get ../ in this case.

It would still work with includegraphics if you use the type and read keys to tell it that it is a jpg file, but usually this is the wrong approach.

  • Amatuer question: Where do I put \tracingmacros1? Should the output be on the pdf or in the log? Also, I copied your post into a file called file and ran grep -E '\->' file | wc -l to make sure my eyes weren't going blind and the result was 12, not 5. I suppose the likely explanation is that I do not understand what you have posted. Oct 30, 2015 at 8:15
  • 1
    sorry 5/12 was just silliness on my part, it seems I can't count:-) If you add the three lines I show anywhere in the document then the log file should have the trace I show, \tracingmacros is an integer register so it's just a normal tex assignment, so you can put it anywhere but if you don't limit the scope with {..} then you get a lot of trace output in the log as you trace ever command. Oct 30, 2015 at 8:25
  • No problem. I suppose 12 expansions is too much for \includegraphics, hm? :-) Thank you for the comment about the internal registers-normal tex assignment. Oct 30, 2015 at 8:28
  • @macmadness86 you can have 10000 expansions in the path part but if you want it to see the .jpg and so automatically detect the image type and use the right back end code you have to not hide that. If you do hide it you need to use type= and the other little used attributes on \includegraphics to give the information in other ways. But I can't see why you'd need to hide the file name. Oct 30, 2015 at 8:33

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .