Search code examples
bashoperator-precedenceheredoc

Precedence of heredocs and compound commands in bash


I want my shell script to print out a simple usage instruction and then exit when it is called without arguments. Here's what I tried:

#!/bin/bash
(($#)) || cat <<EOF && exit

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Usage: Donec a diam lectus.

EOF

echo "You have provided at least one argument"

(The special bash variable $# holds the number of arguments, and surrounding it with double parentheses makes it evaluate to false when there are no arguments).

This works when there are no arguments, but exits immediately without printing anything if there are arguments. I thinks it's due to the wrong precedence of the operators. How can I fix this script to do what I want?


Solution

  • use curly braces to group the commands:

    (($#)) || { cat <<EOF && exit
    Lorem ipsum dolor sit amet, consectetur adipiscing elit.
    
    Usage: Donec a diam lectus.
    
    EOF
    }
    echo "You have provided at least one argument"
    

    Or you could just give up on the compact format, and use if:

    if [[ $# == 0 ]]
    then cat <<EOF && exit
    Lorem ipsum dolor sit amet, consectetur adipiscing elit.
    
    Usage: Donec a diam lectus.
    
    EOF
    fi
    
    echo "You have provided at least one argument"