1

In the following script, I start with set -e to exit if any aspect throws an error. However, the script exits without explanation at the if/elif statement (near last quarter of script below). When the script exits, it does throw an exit status code of 1, though.

I have an echo statement immediately before the if/elif statement that gets printed properly, so I know there's no issue before processing the if/elif statement. The echo statements inside the if and the elif statements do not get printed, suggesting that the conditions of the if/elif statement are not satisfied.

But, the rub is, when I remove the set -e part of the script, the script completes as expected and produces the desired output.

Running the script with: bash -x myscript.sh reveals that the script actually dies at ((cond1_count++)) in the if statement. If I modify those counters in the if/elif statement to different (proper?) formatting (e.g. cond1_count=$((cond1_count+1))), then the script runs just fine with set -e.

Can someone explain why the original ((cond1_count++)) format causes the script to fail with set -e, but proceeds fine without? Just curious and figured this would be a good learning opportunity.

#!/bin/bash

# Exit script if any step fails
set -e


# Array of the various comparisons to evaluate
# Each condition in each comparison should be separated by a "-"
comparisons_array=(
ambient-cold
cold-warm
D9-D12
)

# Functions
# Expects input (i.e. "$1") to be in the following format:
# e.g. 20200413.C_bairdi.113.D9.uninfected.cold.megan_R2.fq
get_day () { day=$(echo "$1" | awk -F"." '{print $4}'); }
get_inf () { inf=$(echo "$1" | awk -F"." '{print $5}'); }
get_temp () { temp=$(echo "$1" | awk -F"." '{print $6}'); }


## Designate input/output file locations/names
samples="${wd}/${comparison}.samples.txt"


# Loop through each comparison
# Will create comparison-specific directories and copy
# appropriate FastQ files for each comparison.

# After file transfer, will create necessary sample list file for use
# by Trinity for running differential gene expression analysis and GO enrichment.
for comparison in "${!comparisons_array[@]}"
do

  # Assign variables
  cond1_count=0
  cond2_count=0
  comparison=${comparisons_array[${comparison}]}
  samples="${comparison}.samples.txt"
  comparison_dir="${wd}/${comparison}/"

  # Extract each comparison from comparisons array
  # Conditions must be separated by a "-"
  cond1=$(echo "${comparison}" | awk -F"-" '{print $1}')
  cond2=$(echo "${comparison}" | awk -F"-" '{print $2}')


  mkdir --parents "${comparison}"

  cd "${comparison}" || exit

  # Create reads array
  # Paired reads files will be sequentially listed in array (e.g. 
  # 20200413.C_bairdi.113.D9.uninfected.cold.megan_R1.fq 
  # 20200413.C_bairdi.113.D9.uninfected.cold.megan_R2.fq)
  reads_array=(*.fq)

  echo ""
  echo "Created reads_array"

  # Loop to create sample list file
  # Sample file list is tab-delimited like this:

  # cond_A    cond_A_rep1    A_rep1_left.fq    A_rep1_right.fq
  # cond_A    cond_A_rep2    A_rep2_left.fq    A_rep2_right.fq
  # cond_B    cond_B_rep1    B_rep1_left.fq    B_rep1_right.fq
  # cond_B    cond_B_rep2    B_rep2_left.fq    B_rep2_right.fq



  # Increment by 2 to process next pair of FastQ files
  for (( i=0; i<${#reads_array[@]} ; i+=2 ))
  do
    echo ""
    echo "Evaluating ${reads_array[i]} and ${reads_array[i+1]}"

    get_day "${reads_array[i]}"
    get_inf "${reads_array[i]}"
    get_temp "${reads_array[i]}"


    echo "Condition 1 is: ${cond1}"
    echo "condition 2 is: ${cond2}"

    # Evaluate specified treatment conditions and format sample file list appropriately.
    if [[ "${cond1}" == "${day}" || "${cond1}" == "${inf}" || "${cond1}" == "${temp}" ]]; then
      ((cond1_count++))

      echo ""
      echo "Condition 1 evaluated."

      # Create tab-delimited samples file.
      printf "%s\t%s%02d\t%s\t%s\n" "${cond1}" "${cond1}_" "${cond1_count}" "${comparison_dir}${reads_array[i]}" "${comparison_dir}${reads_array[i+1]}" \
      >> "${samples}"
    elif [[ "${cond2}" == "${day}" || "${cond2}" == "${inf}" || "${cond2}" == "${temp}" ]]; then
      ((cond2_count++))

      echo ""
      echo "Condition 2 evaluated."

      # Create tab-delimited samples file.
      printf "%s\t%s%02d\t%s\t%s\n" "${cond2}" "${cond2}_" "${cond2_count}" "${comparison_dir}${reads_array[i]}" "${comparison_dir}${reads_array[i+1]}" \
      >> "${samples}"
    fi
  done

  echo "Created ${comparison} sample list file."

  cd "${wd}"
done
John Kugelman
  • 349,597
  • 67
  • 533
  • 578
kubu4
  • 157
  • 13
  • `set -e` does not stop the script, if there is an **error** (because _error_ is a human concept - my error could be your expected behaviour), but stops it if a statement **returns a non-zero exit code**. An arithmetic statement yields exit code `1` if it evaluates to 0. For instance even an innocent `((0))` would stop your script. To see which statement exactly ruins your day in your concrete script, run it under `set -x`. – user1934428 Apr 23 '20 at 07:54

0 Answers0