Home > Back-end >  Run commands on same line as [[ ]] operator
Run commands on same line as [[ ]] operator

Time:12-12

I am attempting to use the [[ ]] operator in Bash and failing badly. My script is:

#!/bin/bash
# Test driver for the ProtectDatae script 
set -o xtrace
# [[ -z "$1" ]] || source="$1" && source=""
if [[ -z "%1" ]]
then
  source=""
else
  source=$1
fi
[[ -z "$2" ]] || target="$2" && target="" # This does not work
[[ -z "$3" ]] || sourceBackup="$3" && sourceBackup="/tmp/sourcebackup" # This does not work
source cmd.sh  # Get a function to run a Linux command
if [[ -e "$sourceBackup" && "$sourceBackup" -ne "" ]]
then
  # If a source backup directory is specified then get rid of any old directory and make a new backup
  # and verify it. If OK, make the source directory be the source backup directory
  # otherwise work directly in the source directory
  if [[ -e "$sourceBackup" ]]
  then
    cmd "sudo rm -R $sourceBackup" "empty backup directory $sourceBackup failed"
    cmd "cp -apu $source $sourceBackup" "backup home directory"
    cmd "diff -aprN ~/$source/* $sourceBackup" "bad backup in $sourceBackup"
    source="$sourceBackup"
 fi
fi

exit 0

My command invocation is ./TestProtectData.sh "~" /tmp/jfghome /tmp/jfgbackup

The result of xtrace is:

  source='~'
  [[ -z /tmp/jfghome ]]
  target=/tmp/jfghome
  target=""
  [[ -z /tmp/jfgbackup ]]
  sourceBackup=/tmp/jfgbackup
  sourceBackup=/tmp/sourcebackup
  source cmd.sh
  [[ -e /tmp/sourcebackup ]]
  exit 0

What happens with the following line is the error. Both alternatives appear to be executed and the variable winds up being set incorrectly:

[[ -z "$2" ]] || target="$2" && target=""

I have tried both orders for && and || and they both give the same result with the variable target set to blank. On the next line, a similar thing happens with the variable sourceBackup set to the second alternative, and both alternatives appear to be executed. If I use the if then construct it works. What am I doing wrong?

CodePudding user response:

What am I doing wrong?

Your intended logic doesn't match the bash constructs you're using. This line:

[[ -z "$2" ]] || target="$2" && target="" # This does not work

Breaks down to mean if 2 is not empty set target to $2. If that command succeeds, set target to "". The command to the left of && will always succeed - either the -z test succeeds or the target="$2" succeeds. Thus target="" always runs at the end.

You can use if ... ; then ...; else ...; fi or you can look at these ways to effect a ternary operator in bash, including:

#!/bin/bash -e
[[ -z "$3" ]] && sourceBackup="/tmp/sourcebackup" || sourceBackup="$3"
echo $sourceBackup
% ./t.sh 1 2 3                                                                                                                                                            
3

Here, if -z test succeeds we set sourceBackup to the default. If the test fails, $3 is not null and we set sourceBackup to $3.

To reiterate, this is not exactly the same as a tertiary operator. But if you get the order correct, it will work.

  • Related