# Change extension of argument to \includegraphics (\includegraphics{xyz.svg} → \includegraphics{xyz.pdf

I'm trying to write a macro which takes a file name as input, changes its extension, and passes that to \includegraphics.

I have seen \includegraphics, try another extension , which gives an alternative solution, but I'm curious to understand why I'm getting endcsname and parameter number errors in my current code (also, that solution doesn't work in xelatex, I think):

\documentclass{article}

\usepackage{graphicx}
\usepackage{xstring}

\usepackage{letltxmacro}
\LetLtxMacro{\IncludeGraphics}{\includegraphics}

\newcommand{\svgtopdf}[1]
{\IfSubStr{#1}{.svg}{\StrSubstitute*{#1}{.svg}}{#1}}

\newcommand{\includegraphicsNaive}[2][]
{\IncludeGraphics[#1]{\svgtopdf{#2}}}

\newcommand{\includegraphicsEdef}[2][]
{\edef\pdfname{\svgtopdf{#2}}
\IncludeGraphics[#1]{\pdfname}}

\newcommand{\includegraphicsNoExpand}[2][]
{\edef\x{\noexpand\IncludeGraphics[#1]{\svgtopdf{#2}}}%
\x{}}

\newcommand{\includegraphicsExpandafter}[2][]
{\IncludeGraphics[#1]\expandafter{\svgtopdf{#2}}}

\begin{document}
\includegraphicsNaive{img.svg} % ERROR: Missing endcsname inserted.
\includegraphicsEdef{img.svg} % ERROR: Illegal parameter number in definition of \pdfname.
\includegraphicsNoExpand{img.svg} % ERROR: Illegal parameter number in definition of \x.
\includegraphicsExpandafter{img.svg} % ERROR: LaTeX Error: File ' not found.
\end{document}

• The first approach was the naive one, and I think the reason it doesn't work is that internally graphicx constructs a command that includes part of the file name argument (the extension of the file) to use a different macro for each file type, and it seems that it doesn't expand its argument before doing that.

• The second approach probably fails for the same reason (\pdfname isn't expanded), but I'm not sure why I get a different error.

• The third one I was hopeful about, and I'm not sure why it doesn't work.

• The last one I think will have expandafter consumed by includegraphics before it can work its magic.

What's the right way?

• The commands of xstring aren't expandable, you can't use the in a edge like this Nov 6 '20 at 7:27
• why not simply \includegraphics{img} why add the .svg extension if it doesn't work? (or use the svg package that will implement this switch of extension Nov 6 '20 at 7:47
• @DavidCarlisle because I don't have control on the document generator. I was not aware of the SVG package; I share my document with other authors who don't necessarily have inkscape installed, so I prefer to pre-generate the SVG. Nov 6 '20 at 16:53

The xstring macros have an optional argument at the end that is used to store the result of the operation in a macro, which can be used in this case.

Also, \StrSubstitute does not have a starred version. Furthermore, you are supposed to provide three arguments: the full string, the search string and the replace string, whereas your MWE only has the full string and the search string. If you want you can leave the replace string empty (\StrSubstitute{#1}{.svg}{}[\tmpname]) to try all available extensions.

Working MWE:

\documentclass{article}

\usepackage{graphicx}
\usepackage{xstring}

\usepackage{letltxmacro}
\LetLtxMacro{\IncludeGraphics}{\includegraphics}

\newcommand{\svgtopdf}[1]
{\IfSubStr{#1}{.svg}{\StrSubstitute{#1}{.svg}{.pdf}[\tmpname]}{\def\tmpname{#1}}}

\newcommand{\includegraphicsNaive}[2][]
{\svgtopdf{#2}%
\IncludeGraphics[#1]{\tmpname}}

\begin{document}
\includegraphicsNaive[width=3cm]{example-image.svg}
\includegraphicsNaive[width=3cm]{example-image-a.pdf}
\includegraphicsNaive[width=3cm]{example-image-b}
\end{document}
`

Result: