# How to include graphics from a complex file structure

I am writing a Latex file that needs to include figures from a directory graphs.

graphs has several sub-directories say, one , two and three. These individually contain several graphics that should be included in the file.

One way is to include every graphic in the file manually. But, that is too cumbersome. Is there a better way to do this?

• So you want to include all graphic files from certain directories automatically? In this case see How to iterate through the name of files in a folder, which looks like a duplicate. The adjustments to multiple directories should be easily done. – Martin Scharrer Dec 20 '11 at 10:00
• @MartinScharrer: Ah. You beat me to the punch. – night owl Dec 20 '11 at 10:08
• You question is not well-defined at the moment. Do you only want to reduce the amount of work, e.g. not have to write the full directory names all the time, or do you want to include all graphic files from a certain directory structure automatically? I personally think it is the later, but looking at the two answers so far other people think more about the former. In that case Automatically Locate Included Images looks like a duplicate. – Martin Scharrer Dec 20 '11 at 10:35
• @Martin: Yea, I guess the question could be a tad bit more specific at what is the optimal goal here. Whether to reduce the typing or have it auto included. – night owl Dec 20 '11 at 10:49
• @MartinScharrer. My main motive here is to reduce the amount of work as I have about 100 plots to include and including each of them one by one is a pain in the bottom – Ankit Dec 21 '11 at 3:29

Put into your preamble:

\graphicspath{{graphs}{graphs/one}{graphs/two}{graphs/three}}


makes sense if you do not have too many subdirectories. Every path is enclosed in braces.

• Hi, But how do I include the files then as each one, two etc have the same file name like a.pdf and b.pdf – Ankit Dec 21 '11 at 3:26
• @Ankit: you can use \graphicspath several times in your document to define other search rules. – user2478 Dec 21 '11 at 8:08

Here is a solution. Comments will be added later.

\documentclass[a4paper,10pt]{article}
\usepackage{graphicx,ifpdf}
\usepackage{ltxkeys}[2011/12/10]
\makeatletter
\ltxkeys@declarekeys*[KV]{importfiles}[fim@]{
cmd/setorlaunch/set;
cmd/processor/\includegraphics/
\ifltxkeys@dec\else
\ifescapedTF{#1}{}{
\edef\fim@processor{\noexpandcsn\fim@processor}
}
\def\reserved@a##1{
\def\reserved@a####1##1####2####3\@nil{
\def\fim@procnr{####2}
\ifx\fim@procnr\@nnil
\@latex@error{Unknown processor \unexpanded{##1}}\@ehc
\fi
}%
\reserved@a\includegraphics{0}\input{1}\include{2}##1{\@nil}\@nil
}%
\s@expandarg\reserved@a\fim@processor
\fi;
cmd/stuffbefore//;
cmd/stuffafter//;
cmd/fileext/tex/
\ifpdf
\ifinsetTF{#1}{,pdf,png,jpeg,jpg,mps,}
{
\edef\fim@graphicsext{#1}
}{
\def\fim@graphicsext{pdf}
}
\else
\def\fim@graphicsext{eps}
\fi;
cmd/inputpaths/./
\ifltxkeys@dec\else
\def\fim@inputpaths{}
\edef\fim@tempa{#1}
\fim@stripbraces\fim@tempa
% \openin will not take spaces in path or filename:
\edef\fim@tempa{\s@expandarg\cptzapspaces\fim@tempa}
\docommalist*\fim@tempa{
\xifinsetTF{/\relax}{##1\relax}{
\edef\fim@inputpaths{\fim@inputpaths\ifbracedTF{##1}{##1}{{##1}}}
}{
\@latex@error{Inputpath '##1' not ended with slash (/)}\@ehc
}
}
\fi;
cmd/scale/1;
cmd/\needvalue{width}//;
cmd/\needvalue{height}//;
cmd/\needvalue{viewport}/0 0 100 100;
bool/clip/true;
choice/align.{
center/\def\fim@align{center},
left/\def\fim@align{flushleft},
right/\def\fim@align{flushright},
justified/\def\fim@align{fim@phantomenv}
}/center;
}
% Why didn't I want to say \let\fim@phantomenv\relax?
\new@def*\fim@phantomenv{\relax}
\robust@def*\fim@stripbraces#1{%
\cptstripallbrincs#1\despacecontent#1\cptstripallbrincs#1%
}
\robust@def*\importfiles{\cpt@testopt\fim@importfiles{}}
\robust@def*\fim@importfiles[#1]#2{%
\usename{ltxkeys@\fim@setorlaunch keys}[KV]{importfiles}{#1}%
% Some paths might have been suggested via \input@path
% and/or \graphicspath. So we heed them here.
\edef\fim@currpaths{%
\ifdefTF\input@path\input@path{}%
\ifdefTF\Ginput@path\Ginput@path{}%
\fim@inputpaths
}%
\edef\fim@tempa{\ifmacroTF{#2}\expandcsonce\unexpanded{#2}}%
\docommalist*\fim@tempa{%
\def\currfile{##1}%
\fim@stripbraces\currfile
\def\siso@do####1{%
\def\currpath{####1}%
\fim@stripbraces\currpath
\ifnum\fim@procnr=\z@pt
\let\currfileext\fim@graphicsext
\else
\let\currfileext\fim@fileext
\fi
\edef\fileonpath{\currpath\currfile.\currfileext}%
% Hmm, why don't I want to use \IfFileExists?
\openin\@inputcheck\fileonpath\relax
\ifcondTF\ifeof\@inputcheck\fi{}{%
\typeout{File '\fileonpath' found}%
\closein\@inputcheck
\fim@doimport
}%
}%
\s@expandarg\siso@@loop\fim@currpaths
}%
}
\robust@def*\fim@doimport{%
\fim@stuffbefore
\begintoksgroup
\ifcase\fim@procnr
\toks@{%
\begin{\fim@align}%
\cptexpanded{%
\noexpand\includegraphics
[viewport=\fim@viewport,scale=\fim@scale,
\ifcsemptyTF\fim@height{}{height=\fim@height,}%
\ifcsemptyTF\fim@width{}{width=\fim@width,}%
\iffim@clip,clip\fi]{\fileonpath}%
}%
\end{\fim@align}%
}%
\or
\toks@{\input\fileonpath}%
\or
\toks@{%
\let\fim@savpath\input@path
\edef\input@path{{\currpath}}%
\fiminclude\currfile
\let\input@path\fim@savpath
}%
\fi
\endtoksgroup
\fim@stuffafter
}
\robust@def*\fiminclude#1{%
\relax
\ifnumcmpTF\@auxout=\@partaux{%
\@latex@error{Command \noexpand\fiminclude cannot be nested}\@ehc
}{%
\edef\reserved@a{\cptzapspaces{#1}}%
\s@expandarg\fim@include\reserved@a
}%
}
\robust@def*\fim@include#1{%
\xifinsetTF{.tex\relax}{#1\relax}{%
\def\reserved@a##1.tex\@nil{%
\def\fim@filename{##1}%
}%
\reserved@a#1\@nil
}{%
\def\fim@filename{#1}%
}%
\clearpage\relax
\if@partsw
% I don't know why LaTeX chose to do a loop here. We don't need it here:
\xifinsetTF{,\fim@filename,}{,\fim@partlist,}%
\@tempswatrue\@tempswafalse
\else
\@tempswatrue
\fi
\ifboolTF{@tempswa}{%
\if@filesw
\immediate\write\@mainaux{\string\@input{\fim@filename.aux}}%
\fi
\let\@auxout\@partaux
\if@filesw
\immediate\openout\@partaux\fim@filename.aux
\immediate\write\@partaux{\relax}%
\fi
\@input@{\fim@filename.tex}%
\clearpage\relax
\@writeckpt{\fim@filename}%
\if@filesw
\immediate\closeout\@partaux
\fi
}{%
\@nameuse{cp@\fim@filename}%
}%
\let\@auxout\@mainaux
}
\robust@def*\fimincludeonly#1{%
\@partswtrue
\cptexpandarg{\cptfiltermergecsv\fim@partlist}
{\cptzapspaces{#1}}\nofilter
}
\cptonlypreamble\fimincludeonly
\makeatother

\fimincludeonly{subfile1a}
\begin{document}
\section{Test section}

\importfiles[
processor   =includegraphics,
viewport    =20 21 590 400,
scale       =.25,
inputpaths  ={D:/MyTempDoc/Path1/,D:/MyTempDoc/Path2/},
stuffbefore =\bigskip\centering Importing \currfile\space from path \currpath\endgraf,
stuffafter  =\endgraf\centering File import succeeded (\currfile).\endgraf
]{
comet1
}

\importfiles[
processor   =include,
inputpaths  ={D:/MyTempDoc/Path1/,D:/MyTempDoc/Path2/}
]{
subfile1a,subfile1b,subfile1c
}

\importfiles[
processor   =\input,
inputpaths  ={D:/MyTempDoc/Path1/,D:/MyTempDoc/Path2/}
]{
subfile1a,subfile1b,subfile1c
}
\end{document}


This is only a partial listing of the code. The full version can handle stand-alone documents in the manner of docmute and standalone packages. I will release it as a package.