39

It is pretty clear that with shell scripting this sort of thing can be accomplished in a huge number of ways (more than most programming languages) because of all the different variable expansion methods and programs like test and [ and [[, etc.

Right now I'm just looking for

DIR=$1 or .

Meaning, my DIR variable should contain either what is specified in the first arg or the current directory.

What is the difference between this and DIR=${1-.}?

I find the hyphen syntax confusing, and seek more readable syntax.

Why can't I do this?

DIR="$1" || '.'

I'm guessing this means "if $1 is empty, the assignment still works (DIR becomes empty), so the invalid command '.' never gets executed."

4
  • 1
    I found my answer to what the colon means: wiki.bash-hackers.org/syntax/pe#use_a_default_value Commented Apr 18, 2013 at 5:07
  • 4
    Embrace the language. Not all languages have the same idioms. DIR=${1:-.} is a perfectly natural way to express this logic in any POSIX-compatible shell. Commented Apr 18, 2013 at 12:26
  • 1
    I find the downvote to be entirely justified. I don't like the way I wrote this question. I was frustrated at the time, I guess. But ever since I posted this, I've never had any trouble remembering the ${VAR:-default} syntax. I'm going to edit my question to make it less petty. I'm sure you weren't the downvoter @chepner but you are absolutely right! Commented Feb 2, 2017 at 19:29
  • I never downvoted (or if I did, I subsequently retracted it). Commented Feb 2, 2017 at 20:24

3 Answers 3

76

I see several questions here.

  1. “Can I write something that actually reflects this logic”

    Yes. There are a few ways you can do it. Here's one:

    if [[ "$1" != "" ]]; then
        DIR="$1"
    else
        DIR=.
    fi
    
  2. “What is the difference between this and DIR=${1-.}?”

    The syntax ${1-.} expands to . if $1 is unset, but expands like $1 if $1 is set—even if $1 is set to the empty string.

    The syntax ${1:-.} expands to . if $1 is unset or is set to the empty string. It expands like $1 only if $1 is set to something other than the empty string.

  3. “Why can't I do this? DIR="$1" || '.'

    Because this is bash, not perl or ruby or some other language. (Pardon my snideness.)

    In bash, || separates entire commands (technically it separates pipelines). It doesn't separate expressions.

    So DIR="$1" || '.' means “execute DIR="$1", and if that exits with a non-zero exit code, execute '.'”.

Sign up to request clarification or add additional context in comments.

1 Comment

just a nitpick. Your first example won't work under set -u, when no argument is given. Perhaps stackoverflow.com/a/18448624/1190453 is a better example.
5

How about this:

DIR=.
if [ $# -gt 0 ]; then
  DIR=$1
fi

$# is the number of arguments given to the script, and -gt means "greater than", so you basically set DIR to the default value, and if the user has specified an argument, then you set DIR to that instead.

1 Comment

This is not horrible, though four lines definitely seems too verbose for my liking. I'd rather just use the hyphen var-expansion since I already know what it means at this point.
1

I use a simple helper function to make such assignments look cleaner. The function below accepts any number of arguments, but returns the first one that's not the empty string.

default_value() {
    # Return the first non-empty argument
    while [[ "$1" == "" ]] && [[ "$#" -gt "0" ]]; do
        shift
    done
    echo $1
}
x=$(default_value "$1" 0)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.