69. CLI Inputs and Outputs

So far, you’ve seen how to pass a single input file to the CLI for it to convert. You can also convert multiple files at once, read content from STDIN, write content to STDOUT, or write content to a different output file or directory. This section explains the various input and output options of the CLI.

69.1. Process Multiple Source Files from the CLI

You can pass multiple source files or a filename pattern to the Asciidoctor CLI and it will convert each file given in turn.

Let’s assume there exist two AsciiDoc files in the current directory, a.adoc and b.adoc. You can pass both files to Asciidoctor using a single command, as follows:

$ asciidoctor a.adoc b.adoc

Asciidoctor will convert both files, transforming a.adoc to a.html and b.adoc to b.html.

To save some typing, you can use the glob operator (*) to match all AsciiDoc files in the current directory using a single argument:

$ asciidoctor *.adoc

Your shell will automatically expand the pattern and interpret the command exactly as you had typed it above:

$ asciidoctor a.adoc b.adoc

You can pass all AsciiDoc files inside direct subfolders using the glob operator (*) in place of the directory name:

$ asciidoctor */*.adoc

To match all files in the current directory and direct subfolders, combine both glob patterns:

$ asciidoctor *.adoc */*.adoc

Since the globs in this command rely on shell expansion, the command is not portable across platforms. To make it portable, you can allow the Asciidoctor CLI to expand the globs. To do so, instruct the shell to not expand the glob by quoting the pattern, as shown here:

$ asciidoctor '*.adoc' '*/*.adoc'

This time, the arguments *.adoc and */*.adoc are passed directly to Asciidoctor instead of being expanded. Asciidoctor handles the glob matching in a manner that is portable across platforms.

If you process multiple nested AsciiDoc files at once and are also applying a custom stylesheet to them, you’ll need to manage the stylesheet’s location.

But it gets better. The glob handling in Asciidoctor (which matches the rules of file globbing in Ruby) is likely more powerful than what your shell offers. For example, you can match AsciiDoc files in the current folder and in folders of any depth using the double glob operator (**).

$ asciidoctor '**/*.adoc'

Most shells do not honor the double glob pattern. Thus, to ensure both portability and flexibility when specifying a glob pattern, always enclose the argument in quotes.

If you specify an output folder, the source folders are not preserved by default. To preserve the folders, specify which portion of the path to remove using the -R flag:

$ asciidoctor -D out -R src 'src/**/*.adoc'

In this case, the folder structure under the src folder will be replicated.

You can use the special value . to indicate you want the folder structure of the source and output to be mirrored exactly. For example:

$ asciidoctor -D out -R . '**/*.adoc'

If you find yourself pushing the boundaries of what can be achieved using the CLI to convert multiple AsciiDoc files (including processing resources like images), consider switching to a build tool like Maven or Gradle. Both tools provide excellent Asciidoctor integration. Refer to the Asciidoctor Maven plugin or Asciidoctor Gradle plugin for details.

69.2. Specifying an Output File

By default, the CLI writes the converted output to the same directory as the input file and with the same name as the input file, except with a file extension that matches the output format (e.g., replacing .adoc with .html). You can override this default and have the CLI write to a file and directory of your choice.

There are several circumstances when you’ll want to specify a different output file:

  • You want to write the output file to a different name, perhaps to append a qualifier such as a version string.

  • You want to write the output file to a different directory.

  • You are piping content to the CLI, but want to write the output to a file (in this case, an output file is required).

By specifying an output file, you implicitly overwrite the output directory as well. The output file will be resolved relative to the current working directory, not the directory of the input file.

To specify the output file, you’ll use the -o option. For example, let’s say we want to convert mydoc.adoc and write the output to a filename that includes the current date. You’d use:

$ asciidoctor -o mydoc-$(date +%Y-%m-%d).html mydoc.adoc

We could write it to another folder as well by prefixing the output file with a folder name:

$ asciidoctor -o build/mydoc-$(date +%Y-%m-%d).html mydoc.adoc

If you only want to specify the output directory, but let the filename be defaulted, use the -D option:

$ asciidoctor -D build mydoc.adoc

The -D option can also be used when processing multiple input files:

$ asciidoctor -D build *.adoc

If you are piping content to the CLI, the default is to write the output to STDOUT. If you want to write the output to a file in this case, you have to specify one:

$ cat mydoc.adoc | asciidoctor -o build/mydoc-$(date +%Y-%m-%d).html -

You’ll learn more about piping content through the CLI in the next section.

69.3. Piping Content Through the CLI

Using the - flag, you can pipe content to the asciidoctor command. This flag tells Asciidoctor read the source from standard input (STDIN). For example:

$ echo 'content' | asciidoctor -
Any variation of STDIN will work.

This command is effectively the same as:

$ echo 'content' | asciidoctor -o - -

When reading source from STDIN, Asciidoctor doesn’t have a reference to an input file. Therefore, it sends the converted text to standard output (STDOUT) by default.

If, instead, you want to write the full document to an output file, you specify it using the -o flag. For example, the following command writes a standalone HTML document to output.html instead of STDOUT:

$ echo "content" | asciidoctor -o output.html -

When you pipe content to the asciidoctor command, it no longer has a concept of where the document is located. Therefore, relative references such as includes may not work as expected. To resolve this problem, you should specify an absolute base directory using the -B option:

$ echo "content" | asciidoctor -B /path/to/basedir -o output.html -

Alternately, you can set an artificial document directory by passing an absolute path to the docdir attribute:

$ echo "content" | asciidoctor -a docdir=/path/to/docdir -o output.html -

Try both approaches to determine which one suits your needs better.

When piping source from STDIN to STDOUT through the asciidoctor command, you often just want the converted body (i.e., embeddable HTML). To produce that variant, add the -s flag:

$ echo 'content' | asciidoctor -s -

Or perhaps you want to include the doctitle as well:

$ echo -e '= Document Title\n\ncontent' | asciidoctor -s -a showtitle -