5

I am trying to have all auxilliary files created in a "_build" subdirectory, but automatically move the created PDF back to the same directory as the .tex.

In other words, I want the .tex and .pdf in one folder, and the other build files in a "_build" folder.

I think I can achieve this with arara's move command. But I can't work out how to automate the filename.

MWE:

% arara: lualatex: { options:  [ '--output-directory=_build' ], draft: true }
% arara: biber: { options: ['--output_directory=_build'] }
% arara: lualatex: { options:  [ '--output-directory=_build' ], synctex: true }
% arara: lualatex: { options:  [ '--output-directory=_build' ], synctex: true }
% arara: move: {  files: [ '_build/tmp.pdf' ], target: ['./'] }

\documentclass{report}
\usepackage{lipsum}
\begin{document}
  \lipsum[5]
\end{document}

I'd rather not need to change the preamble for every new document or filename change. But I can't work out how to get something like this to work:

% arara: move: {  files: [ '_build/@{getBasename(currentFile())}.pdf' ], target: ['./'] }

How can I achieve this?

2
  • I'm pretty sure this is an error in two steps: First of all, in files there is no orb-tag expansion so your getBasename call won't work. Second, with fixed file name it works for me (on Linux), so you probably omit some relevant details.
    – TeXnician
    Oct 26, 2021 at 12:06
  • The MWE above does work. The problem is that I want this to be a template I can use many times and it will have a different filename each time. Rather than needing to change the filename each time, I was hoping to automate finding it.
    – jw5801
    Oct 26, 2021 at 15:08

1 Answer 1

6

As mentioned in the comments, orb tag expansion is allowed only within options and no other key, so the attempt of expanding the base name reference inside files will fail. This is by design, as the team don't want arbitrary orb tag expansion. That said, feature requests are always welcome. :)

The typical way to tackle this scenario would be with a custom rule, perhaps with an extension of the existing move one. However, in this answer, I will take another route and provide a solution within the conditional scope using MVEL and Java methods:

% arara: lualatex: { options:  [ '--output-directory=_build' ] }
% arara: halt if a = getOriginalReference().getName();
% arara: --> b = a.substring(0, a.lastIndexOf('.'));
% arara: --> c = toFile(b + '.pdf');
% arara: --> d = toFile('_build/' + b + '.pdf');
% arara: --> d.renameTo(c); true

\documentclass{report}
\usepackage{lipsum}
\begin{document}
\lipsum[5]
\end{document}

Let us break down what's happening here, from the second line on:

% arara: halt if a = getOriginalReference().getName();

I will use the halt directive for this case, as it simply halts the tool. The first part of the conditional gets the original reference (regardless of files) and extract the file name, as a string. The variable a then holds just the .tex file name (without path reference).

% arara: --> b = a.substring(0, a.lastIndexOf('.'));

Variable b holds the file name from a without its corresponding extension. This would be equivalent to getting the base name, so e.g., if a = foo.tex, then b = foo.

% arara: --> c = toFile(b + '.pdf');

Variable c now holds the file base name plus the .pdf suffix, as a File reference.

% arara: --> d = toFile('_build/' + b + '.pdf');

Similarly, variable d holds the file base name plus the .pdf suffix, appended to the _build/ string, indicating the path location. The variable holds all of this as a File reference.

% arara: --> d.renameTo(c); true

Now, having two File references, we simply tell d to be renamed to c by using the renameTo(...) method from Java. Finally, I simply end the conditional with true, which indicates that halt should proceed.

Hope it helps. :)

Update from comments: when using renameTo(...), one might observe that the behaviour of this method is inherently platform-dependent. A possible alternative to this is exploiting the move operation from NIO Files with StandardCopyOption. Replace the last directive line

% arara: --> d.renameTo(c); true

by

% arara: --> java.nio.file.Files.move(d.toPath(), c.toPath(),
% arara: --> java.nio.file.StandardCopyOption.REPLACE_EXISTING);
% arara: --> true

and that should do the job.

4
  • Thanks for this very detailed answer! I have only one issue with the solution: if the .pdf already exists in the base directory, this silently fails. How would I tell the renameTo() method from Java to overwrite an existing file?
    – jw5801
    Oct 26, 2021 at 15:15
  • I have also added a c.delete() step to remove the .pdf if it already exists, though there might be a better way to handle overwriting the file?
    – jw5801
    Oct 26, 2021 at 15:21
  • 1
    @jw5801 I wrote an addendum, hope it helps. :) Oct 26, 2021 at 15:49
  • ERROR MSG: For whatever reason, I could not compile the expression in the provided conditional. This part is quite tricky, since it involves aspects of the underlying expression language. I will do my best to help you in any way I can. There are more details available on this exception: DETAILS --------------------------------------------------------- [Error: unable to resolve method: org.islandoftex.arara.api.files.MPPPath.getName() [arglength=0]] [Near : {... @{ a = getOriginalReference(). ....}] ^ [Line: 1, Column: 1]
    – Krantz
    Aug 13, 2023 at 13:25

You must log in to answer this question.

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