Bash Apps
Learn to write a basic Bash app .
Last updated
Learn to write a basic Bash app .
Last updated
Copyright 2024 DNAnexus
If you have not already, you should install the DNAnexus SDK and walk through the Intro to Building Apps tutorial.
Bash apps are the simplest apps you can create on DNAnexus. They include a shell script which runs on a virtual machine on the cloud. The script, written by the app developer, is responsible for downloading inputs, processing, and uploading outputs.
There are two ways to download inputs: one by one, or all at once.
To download all inputs at once (recommended), use the dx-download-all-inputs
utility. Add "--parallel"
to allow multiple downloads in parallel:dx-download-all-inputs --parallel.
Inputs are downloaded to a folder called "in" under the home folder. Each input is placed under its own subfolder "~/in/name_of_input_field/"
, named after the input field. Files retain their original filenames as supplied by the user who launched the applet.
For example, if your applet defines a file input called "mappings" and a user runs it with a file called "SRR001.bam"
, it will be downloaded into ~/in/mappings/SRR001.bam
.
The system defines the following helper bash variables, which you can use in your applet:
The variable $mappings_prefix
is automatically computed by the system by starting from the filename and removing any suffixes that match the patterns specified in dxapp.json
for this input field.
To download inputs one by one, use the following syntax:
dx download "$name_of_input_field"
This will download the file to the current working directory. It will retain the original file as supplied by the user who launched the applet. You can use the "$xxxxxx_name"
variable (as shown in the table above) to refer to that filename.
To name the local file using a different name than the original filename, use the following syntax:
dx download "$name_of_input_field" -o local_filename
To stream the local file and pipe it to another command, use the following syntax:
dx cat "$name_of_input_field" | command
You can combine these strategies. You can download or stream some inputs one by one, and the rest all at once, using the following syntax:
dx-download-all-inputs --except name_of_input_field1 --except name_of_input_field2
dx download "$name_of_input_field1"
dx cat "$name_of_input_field2" | command
An alternative to dx-download-all-inputs
is the dx-mount-all-inputs
command-line utility. You can use it by adding this line to your script.sh:
$ dx-mount-all-inputs
dxfuse
is required for the dx-mount-all-inputs
to work. You can download the dxfuse
binary from https://github.com/dnanexus/dxfuse/releases and add it to ./resources/usr/bin/dxfuse
.
dx-mount-all-inputs
uses the same directory structure as illustrated above for dx-download-all-inputs
, except that the files are mounted to the respective location rather than downloaded. When using dx-mount-all-inputs
, input files do not take up local storage because they are mounted using Linux FUSE technology and streamed behind the scenes transparently when accessed.
There are two ways to upload outputs: one by one, or all at once.
To upload outputs one by one, use the following syntax:
id=$(dx upload /path/to/local/file --brief)
dx-jobutil-add-output name_of_output_field "$id"
If you would like the uploaded file to have a different name than the local file, add the following to the dx upload command:
--path remote_filename
If you would like the uploaded file to appear under a subfolder in the applet outputs, add the following to the dx upload command:
--path /subfolder/remote_filename --parents
If you would like the uploaded file to contain metadata, for example set a property (key/value pair), add the following to the dx upload command:
--property key=value
To upload all outputs at once, create a folder "out" under the home folder, and create a subfolder named after each output field. Place a file under each subfolder, and call the "dx-upload-all-outputs" utility:
mkdir -p ~/out/name_of_output_field1/ ~/out/name_of_output_field2/
mv file1 ~/out/name_of_output_field1/
mv file2 ~/out/name_of_output_field2/
dx-upload-all-outputs
If you would like any uploaded file to have a different name than the local file, rename them as you move them:
mv file1 ~/out/name_of_output_field1/renamed_file1
If you would like any uploaded file to appear under a subfolder in the applet outputs, create the subfolder like this:
mkdir -p ~/out/name_of_output_field1/subfolder/
mv file1 ~/out/name_of_output_field1/subfolder/
If you would like the uploaded files to contain metadata, for example set a property (key/value pair), make the following changes:
Install the "attr" Linux executable by specifying the "attr" Ubuntu package in your dxapp.json
.
For each file, and for each key/value pair you would like to attach, set the respective Linux extended file system attribute like this:
attr -s key -V value ~/out/name_of_output_field1/file1
Add "--xattr-properties"
to the dx-upload-all-outputs invocation:
dx-upload-all-outputs --xattr-properties
Bash variable
Content
$mappings_path
~/in/mappings/SRR001.bam
$mappings_name
SRR001.bam
$mappings_prefix
SRR001
$mappings
{"$dnanexus_link": "file-F77Bp7002302Zb343BF1FpG0"}