2.7. Outputs#

2.7.1. Returning Output Files#

The outputs of a tool is a list of output parameters that should be returned after running the tool. Each parameter has an id for the name of parameter, and type describing what types of values are valid for that parameter.

When a tool runs under CWL, the starting working directory is the designated output directory. The underlying tool or script must record its results in the form of files created in the output directory. The output parameters returned by the CWL tool are either the output files themselves, or the result of examining the content of those files.

The following example demonstrates how to return a file that has been extracted from a tar file.

Tip

Passing mandatory arguments to the baseCommand

In previous examples, the baseCommand was just a string, with any arguments passed as CWL inputs. Instead of a single string, we can use an array of strings as the value of baseCommand. The first element of the array is the command to run, and any subsequent elements are mandatory command line arguments

tar.cwl#
#!/usr/bin/env cwl-runner
cwlVersion: v1.2
class: CommandLineTool
baseCommand: [tar, --extract]
inputs:
  tarfile:
    type: File
    inputBinding:
      prefix: --file
outputs:
  example_out:
    type: File
    outputBinding:
      glob: hello.txt
tar-job.yml#
tarfile:
  class: File
  path: hello.tar

Next, create a tar file for the example.

$ touch hello.txt && tar -cvf hello.tar hello.txt
hello.txt

And now invoke cwltool with the tool description and the input object on the command line:

$ cwltool tar.cwl tar-job.yml
INFO /opt/hostedtoolcache/Python/3.9.19/x64/bin/cwltool 3.1.20240508115724
INFO Resolved 'tar.cwl' to 'file:///home/runner/work/user_guide/user_guide/src/_includes/cwl/outputs/tar.cwl'
INFO [job tar.cwl] /tmp/nztrkqq8$ tar \
    --extract \
    --file \
    /tmp/a54yrw9l/stg10c9d2e8-602f-48ba-ad54-8ca4886c7943/hello.tar
INFO [job tar.cwl] completed success
{
    "example_out": {
        "location": "file:///home/runner/work/user_guide/user_guide/src/_includes/cwl/outputs/hello.txt",
        "basename": "hello.txt",
        "class": "File",
        "checksum": "sha1$da39a3ee5e6b4b0d3255bfef95601890afd80709",
        "size": 0,
        "path": "/home/runner/work/user_guide/user_guide/src/_includes/cwl/outputs/hello.txt"
    }
}INFO Final process status is success

The field outputBinding describes how to set the value of each output parameter.

outputs:
  example_out:
    type: File
    outputBinding:
      glob: hello.txt

The glob field consists of the pattern to match file names in the output directory. This can simply be the file’s exact name. But if you don’t know the name of the file in advance, you can use a wildcard pattern like glob: '*.txt'.

2.7.2. Capturing Standard Output#

To capture a tool’s standard output stream, add the stdout field with the name of the file where the output stream should go. Then add type: stdout on the corresponding output parameter.

stdout.cwl#
#!/usr/bin/env cwl-runner
cwlVersion: v1.2
class: CommandLineTool
baseCommand: echo
stdout: output.txt
inputs:
  message:
    type: string
    inputBinding:
      position: 1
outputs:
  example_out:
    type: stdout
echo-job.yml#
message: Hello world!

Now invoke cwltool providing the tool description and the input object on the command line:

$ cwltool stdout.cwl echo-job.yml
INFO /opt/hostedtoolcache/Python/3.9.19/x64/bin/cwltool 3.1.20240508115724
INFO Resolved 'stdout.cwl' to 'file:///home/runner/work/user_guide/user_guide/src/_includes/cwl/outputs/stdout.cwl'
INFO [job stdout.cwl] /tmp/u76bobi4$ echo \
    'Hello world!' > /tmp/u76bobi4/output.txt
INFO [job stdout.cwl] completed success
{
    "example_out": {
        "location": "file:///home/runner/work/user_guide/user_guide/src/_includes/cwl/outputs/output.txt",
        "basename": "output.txt",
        "class": "File",
        "checksum": "sha1$47a013e660d408619d894b20806b1d5086aab03b",
        "size": 13,
        "path": "/home/runner/work/user_guide/user_guide/src/_includes/cwl/outputs/output.txt"
    }
}INFO Final process status is success

2.7.3. Array Outputs#

You can also capture multiple output files into an array of files using glob.

array-outputs.cwl#
#!/usr/bin/env cwl-runner
cwlVersion: v1.2
class: CommandLineTool
baseCommand: touch
inputs:
  touchfiles:
    type:
      type: array
      items: string
    inputBinding:
      position: 1
outputs:
  output:
    type:
      type: array
      items: File
    outputBinding:
      glob: "*.txt"
array-outputs-job.yml#
touchfiles:
  - foo.txt
  - bar.dat
  - baz.txt

Now invoke cwltool providing the tool description and the input object on the command line:

$ cwltool array-outputs.cwl array-outputs-job.yml
INFO /opt/hostedtoolcache/Python/3.9.19/x64/bin/cwltool 3.1.20240508115724
INFO Resolved 'array-outputs.cwl' to 'file:///home/runner/work/user_guide/user_guide/src/_includes/cwl/outputs/array-outputs.cwl'
INFO [job array-outputs.cwl] /tmp/gj8xthx7$ touch \
    foo.txt \
    bar.dat \
    baz.txt
INFO [job array-outputs.cwl] completed success
{
    "output": [
        {
            "location": "file:///home/runner/work/user_guide/user_guide/src/_includes/cwl/outputs/baz.txt",
            "basename": "baz.txt",
            "class": "File",
            "checksum": "sha1$da39a3ee5e6b4b0d3255bfef95601890afd80709",
            "size": 0,
            "path": "/home/runner/work/user_guide/user_guide/src/_includes/cwl/outputs/baz.txt"
        },
        {
            "location": "file:///home/runner/work/user_guide/user_guide/src/_includes/cwl/outputs/foo.txt",
            "basename": "foo.txt",
            "class": "File",
            "checksum": "sha1$da39a3ee5e6b4b0d3255bfef95601890afd80709",
            "size": 0,
            "path": "/home/runner/work/user_guide/user_guide/src/_includes/cwl/outputs/foo.txt"
        }
    ]
}INFO Final process status is success

As described in the YAML Guide, the array of expected outputs is specified in array-outputs-job.yml with each entry marked by a leading -. This format can also be used in CWL descriptions to mark entries in arrays, as demonstrated in several of the upcoming sections.