问题
I have a bash script like below. First it will take sorted.bam files as input and use "stringtie" tool give each sample gtf as output. Then path for each sample gtf will be given into mergelist.txt. and then use "stringtie merge" on them to get "stringtie_merged.gtf".
I totally have 40 sorted.bam files.
for sample in /path/*.sorted.bam
do
dir="/pathto/hisat2_output"
dir2="/pathto/folder"
base=`basename $sample '.sorted.bam'`
"stringtie -p 8 -G gencode.v27.primary_assembly.annotation_nochr.gtf -o ${dir2}/stringtie_output/${base}/${base}_GRCh38.gtf -l ${dir2}/stringtie_output/${base}/${base} ${dir}/${base}.sorted.bam; ls ${dir2}/stringtie_output/*/*_GRCh38.gtf > mergelist.txt; stringtie --merge -p 8 -G gencode.v27.primary_assembly.annotation_nochr.gtf -o ${dir2}/stringtie_output/stringtie_merged.gtf mergelist.txt"
done
I separated the commands with ;
After running the script on all sorted.bam files and after completing the job I see that mergelist.txt has paths only for 33 sample gtf's. Which means the path for other 7 sample gtfs is missing in merge list.txt.
Is Separating the commands with ;
right one or is there any other way?
The script should use one command first and with the output the paths need to be given in the text file and then use the other command.
回答1:
You haven't separated the commands with semi-colons; you've invoked a single command that has semi-colons embedded in it. Consider the simple script:
"ls; pwd"
This script does not call ls
followed by pwd
. Instead, the shell will search the PATH looking for a file named ls; pwd
(that is, a file with a semi-colon and a space in its name), probably not find one and respond with an error message. You need to remove the double quotes.
回答2:
What's wrong with multiple lines, as you already have more than one line:
dir="/pathto/hisat2_output"
dir2="/pathto/folder"
for sample in /path/*.sorted.bam ;do
base=$(basename ${sample} '.sorted.bam')
stringtie -p 8 -G gencode.v27.primary_assembly.annotation_nochr.gtf -o ${dir2}/stringtie_output/${base}/${base}_GRCh38.gtf -l ${dir2}/stringtie_output/${base}/${base} ${dir}/${base}.sorted.bam
ls ${dir2}/stringtie_output/*/*_GRCh38.gtf > mergelist.txt
stringtie --merge -p 8 -G gencode.v27.primary_assembly.annotation_nochr.gtf -o ${dir2}/stringtie_output/stringtie_merged.gtf mergelist.txt
done
Anyway, I don't see the point in having the second stringtie command inside the loop, it should work fine just after.
If stringtie is able process STDIN you might get away without the mergelist.txt by using:
stringtie --merge -p 8 -G gencode.v27.primary_assembly.annotation_nochr.gtf -o ${dir2}/stringtie_output/stringtie_merged.gtf <<< $(echo ${dir2}/stringtie_output/*/*_GRCh38.gtf)
回答3:
you should double quote your variables and use $( command )
instead backticks
base=$( basename $sample '.sorted.bam' )
:
you have a space in filenames??
prefer:
base=$( basename "$sample.sorted.bam" ) # with or without space
if you have spaces, you must double quote:
stringtie -p 8 \
-G gencode.v27.primary_assembly.annotation_nochr.gtf \
-o "$dir2/stringtie_output/$base/$base_GRCh38.gtf" \
-l "$dir2/stringtie_output/$base/$base" \
"$dir/$base.sorted.bam"
ls "$dir2"/stringtie_output/*/*_GRCh38.gtf > mergelist.txt
...
来源:https://stackoverflow.com/questions/49629366/how-to-make-the-bash-script-work-with-one-command-after-another