What is the best way to write values from a channel to a file?
Consider the following example:
nextflow.enable.dsl=2
workflow {
ch = Channel.of('a', 'b', 'c')
file('test.txt').withWriter {out ->
out.println "My values are:"
ch.subscribe {
out.println "$it"
println "$it"
}
}
}
This will correctly output a
, b
, c
to stdout, but test.txt
will only contain My values are:
and nothing else. Clearly, .subscribe{}
is iterating over the values (otherwise it wouldn't display them to stdout) and writing to the file is working (otherwise the file would not have My values are:
), but why would it not write the values to the file?
The usual way is to use the collectFile
operator: https://nextflow-io.github.io/patterns/collect-into-file/
If you don't need sorted output and would like the entries appended as they're emitted, you could also use sort: false
to disable content sorting and the concat
operator to prepend the header:
workflow {
my_header = Channel.value( "My values are:" )
my_values = Channel.of( 'foo', 'bar', 'baz' )
my_header
.concat( my_values )
.collectFile( name: 'test.txt', newLine: true, sort: false )
.view()
}
Results:
$ nextflow run main.nf
N E X T F L O W ~ version 23.04.1
Launching `main.nf` [marvelous_marconi] DSL2 - revision: c9242fbc73
/path/to/work/tmp/ea/d8ec4488443faf816cb6a213f3bad7/test.txt
Contents of
/path/to/work/tmp/ea/d8ec4488443faf816cb6a213f3bad7/test.txt
:
My values are:
foo
bar
baz
Note that you could also use a closure to write to the file, for example:
workflow {
def test_file = new File( 'test.txt' )
def write_value = { value ->
test_file << value + "\n"
}
my_values = Channel.of( 'foo', 'bar', 'baz' )
Channel
.value( "My values are:" )
.concat( my_values )
.subscribe { write_value(it) }
}
$ cat test.txt
My values are:
foo
bar
baz