Reputation: 100
Hi i have script as below:
mode= loop1 or loop2
command1="screen -dm -S $name feh *.jpg"
if [ "$(screen -S loop1 -X select . ; echo $?)" != 0 ] && [[ $mode != "loop1" ]];then
name="loop1"
eval "$command1"
elif [ "$(screen -S loop2 -X select . ; echo $?)" != 0 ] && [[ $mode != "loop2" ]] ;then
name="loop2"
eval "$command1"
else
echo "error"
fi
Basically it check if there is screen session named loop1 or loop2 if there is not, it evaluate variable $command1 which inside have another variable $name which should have change when the bash get inside loop. the problem is that variable $command1 is initialized globally before if statement start and in that time there is no variable $date.
When loop evaluate $command1 it do not use variable $name setted line before in loop statement.
I need pass to the variable command1 value of variable name
Do you have any clue ?
Upvotes: 0
Views: 135
Reputation: 81022
While chepner is entirely correct that you are going to run into Bash FAQ 050 problems and you shouldn't try to do that.
The more immediate problem here is an evaluation order issue.
When the shell runs this line command1="screen -dm -S $name feh *.jpg"
it is expanding $name
at that point (which, as you'll notice, is before you've assigned the name variable a value).
Switching the order of those (groups of) lines would work for this issue but wouldn't do anything for the other Bash FAQ 050 issues.
Additionally, [ "$(screen -S loop1 -X select . ; echo $?)" != 0 ]
is an inefficient and unnecessary way to test a command for a successful return code.
[
is a command (also known as test
). It isn't an integral part of the syntax of an if
statement.
The syntax of an if
statement in the shell is if <command>; then ... fi
where <command>
can be anything that returns a return code appropriately. [
just happens to be a commonly used command in that space.
But if your command (screen -S loop1 -X select .
in this case) already returns success/failure appropriately then you can avoid [
entirely and just use your command.
if ! screen -S loop1 -X select . && [[ $mode != "loop1" ]];then
name="loop1"
elif ! screen -S loop2 -X select . && [[ $mode != "loop2" ]] ;then
name="loop2"
else
echo "error"
fi
Upvotes: 1
Reputation: 189789
As already pointed out in a comment, this is a FAQ: http://mywiki.wooledge.org/BashFAQ/050
A sensible workaround is to refactor the command into a parametrized function. The conditionals should also be cleared up of pretzel logic -- printing a command's exit code and comparing it to the string zero is a clumsy way to reimplement the basic functionality of the built-in if
conditional!
mode=loop1 # or loop2
run_feh (} {
screen -dm -S "$1" feh *.jpg
}
no_screen_of_loop () {
! screen -S "$1" -X select . && [[ "$2" != "$1" ]]
}
if no_screen_of_loop "loop1" "$mode"; then
run_feh "loop1"
elif no_screen_of_loop "loop2" "$mode"; then
run_feh "loop2"
else
echo "error" >&2 # note stderr
fi
If having a value in $name
after the conditional is necessary, a slight additional refactoring will be necessary.
Upvotes: 2
Reputation: 1
It should work:
mode= loop1 or loop2
command1="screen -dm -S name feh *.jpg"
if [ "$(screen -S loop1 -X select . ; echo $?)" != 0 ] && [[ $mode != "loop1" ]];then
eval "${command1/name/loop1}"
elif [ "$(screen -S loop2 -X select . ; echo $?)" != 0 ] && [[ $mode != "loop2" ]] ;then
eval "${command1/name/loop2}"
else
echo "error"
fi
Upvotes: 0