I want to execute echo only if one of the folders are not found?
However AEM_SEGMENTSTORE_LOCATION_AZURE is found but I still get "echo not found"
#!/bin/bash
AEM_SEGMENTSTORE_LOCATION="/opt/day/${AEM_RUNMODE}/crx-quickstart/repository/segmentstore"
AEM_SEGMENTSTORE_LOCATION_AZURE="/opt/day/crx-quickstart/repository/segmentstore"
[[ ! -d ${AEM_SEGMENTSTORE_LOCATION} ]] || [[ ! -d ${AEM_SEGMENTSTORE_LOCATION_AZURE} ]] && echo "not found"
In general, don't mix || and &&. The precedence is not what you expect. a || b && c is equivalent to (a || b) && c, but a && b || c is not the same as (a && b) || c. Get in the habit of using a proper if statement.
if [[ ! -d "$AEM_SEGMENTSTORE_LOCATION" || ! -d "$AEM_SEGMENTSTORE_LOCATION_AZURE" ]]; then
echo "not found"
fi
or
if ! [[ -d "$AEM_SEGMENTSTORE_LOCATION" && -d "$AEM_SEGMENTSTORE_LOCATION_AZURE" ]]; then
echo "not found"
fi
The precedence is wrong. You seem to be looking for AND anyway. You can easily fix this by changing it to
if [[ ! -d "$AEM_SEGMENTSTORE_LOCATION" ]] &&
[[ ! -d "$AEM_SEGMENTSTORE_LOCATION_AZURE" ]]
then
echo "$0: not found" >&2
fi
Notice also proper quoting of your variables {see When to wrap quotes around a shell variable; braces do not quote, and were basically useless here) and probably avoid uppercase variable names if these are private variables of yours (uppercase is reserved for system variables). Finally, the diagnostic message should probably go to standard error, and include the script's name; it should probably also say what was not found.
Related
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?
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.
A plain assignement (foo=bar) always sets the status code to 0, so after target has been set to $2, it is immediately after set to empty. I would start by turning the logic inside out:
target= # Set to empty string
[[ -z $2 ]] && target=$2
However, this is redundant. You could easier simply just write
target=$2
without doing any [[...]]-test. If the second parameter is empty, target will be empty as well. If it is not empty, target will get that value.
There is one point to consider: In case you decide to turn on set -u, to catch uninitialized variables, a target=$2 would abort the script if there is no second parameter. Therefore, you could also write
target=${2:-}
which tells bash that a missing parameter is OK and should be treated as a null string.
Even though it is redundant, if you do not turn on -u, using ${2:-} shows your intent explicitly, and makes your program more maintainable.
I am having a trouble checking if a branch exists in a Jenkins job.
My shell scripts is as follows:
set +e
BRANCH_EXISTS=$(git ls-remote --quiet | grep -w ${BRANCH_NAME})
if [[ -z $"{BRANCH_EXISTS}" ]]
then
echo "Branch does not exist"
else
echo "Branch exists"
fi
Following is a log:
07:36:26 + BRANCH_EXISTS='4cbe2d1776db4dc263a1e7884e35da49a0a6f309 refs/heads/equalizer_fe_testing'
07:36:26 + [[ -z {BRANCH_EXISTS} ]]
07:36:26 + echo 'Branch exists'
07:36:26 Branch exists
...
07:36:27 + BRANCH_NAME=test/fe-testing_staging1
07:36:27 ++ grep -w test/fe-testing_staging1
07:36:27 ++ git ls-remote --quiet
07:36:28 + BRANCH_EXISTS=
07:36:28 + [[ -z {BRANCH_EXISTS} ]]
07:36:28 + echo 'Branch exists'
07:36:28 Branch exists
07:36:29 Finished: SUCCESS
As you can see, in one case I check for a branch that does not exist. But still the if condition passes. I have tried with if [[ -n $"{BRANCH_EXISTS}" ]] as well but still gets the same result.
What am I doing wrong here?
You are incorrectly using the test operator to check if string is empty. In most shells, variable interpolation happens with ${var} and not {var} or $"{var}"
$ var=foo
$ [[ -z $var ]] && echo ok
$ [[ -z $var ]] || echo ok
ok
$ var=
$ [[ -z $var ]] && echo ok
ok
$ [[ -z var ]] && echo ok # does not assert, because literal 'var' is not empty
When you are doing [[ -z {var} ]] you are not interpolating var, but comparing against a literal string {var} which is never empty.
Change your conditional to [[ -z "${BRANCH_EXISTS}" ]] to make it work as expected.
As Inian already explained in his answer, $"{BRANCH_EXISTS}", but "${BRANCH_EXISTS}" would be correct. However, there is more to it:
In your case, the double quotes are not necessary, because no word splitting occures here after parameter expansion (since you are inside a [[....]]. Hence you can write simply [[ -z $BRANCH_EXISTS ]].
However, if the branch does not exist, grep will return a non-zero exit code, and the program will be aborted (due to your set -e. Therefore, the then branch of your conditional won't ever be executed, even if you would fix the conditional.
I made a short script that changes all files with one extension to a different extension. Both extensions are inputted by the user through command line arguments. I put in an if statement to handle errors but for some reason it considers everything an error and I am not sure why. I have pasted the script below. I am rather new to bash scripting so any help would be greatly appreciated!
if [[ "$#" == 0 ]] || [[ "$1" || "$2" != "."* ]]
then
echo "Parameters are not valid"
exit
fi
for f in *"$1"; do
name=${f%.*}
mv $f "$name$2"
done
[[ "$1" || "$2" != "."* ]] should be [[ "$1" != .* ]] || [[ "$2" != .* ]]
Is it possible to override Bash's test builtin? So that
[[ $1 = 'a' ]]
not just does the test but also outputs which result was expected when it fails? Something like
echo "Expected $1 to be a.'
EDIT
I know this is bad :-).
The test expression compound command does real short-circuiting that affects all expansions.
$ set -x
$ [[ 0 -gt x=1+1 || ++x -eq $(tee /dev/fd/3 <<<$x) && $(echo 'nope' >&3) ]] 3>&1
+ [[ 0 -gt x=1+1 ]]
++ tee /dev/fd/2
2
+ [[ ++x -eq 2 ]]
So yes you could do anything in a single test expression. In reality it's quite rare to have a test produce a side-effect, and almost never used to produce output.
Also yes, reserved words can be overridden. Bash is more lenient with ksh-style function definitions than POSIX style (which still allows some invalid names).
function [[ { [ "${#:1:${##}-1}" ]; }; \[[ -a -o -a -o -a ]] || echo lulz
Yet another forky bomb.
if function function if function if if \function & then \if & fi && \if & then \function & fi && then \function fi
Something like this?
if [[ $1 == 'a' ]]; then
echo "all right";
else
echo 'Expected $1 to be "a"'
fi
Anyway, what's the point of the test if you only expect one answer? Or do you mean that for debugging purposes?
[[ 'a' = 'a' ]] || echo "failed"
[[ 'b' = 'a' ]] || echo "failed"
failed
This code is not working, but I don't know what's wrong.
If I only use single brackets the string isn't compared right.
#!/bin/bash
forceupdate=false
currentVersion=520-19
latestVersion=520-19
if [[ "$latestVersion" > "$currentVersion" -o forceupdate ]]
then
echo -e "\nupdate!\n"
else
echo -e "\nno update!\n"
fi
$forceupdate inside brackets will actually be true, because it's not going to execute the false executable, but it will see a non-empty string.
if [[ "$latestVersion" > "$currentVersion" ]] || $forceupdate