I am facing problems running two commands one after another in bash.  When I run

source2() { '/home/ds/Documents/scripts/Untitled Document 1.sh' && imgpath="$(ls | grep "^unsplash")" }

source3()  {  '/home/ds/Documents/scripts/Untitled Document 2.sh' && imgpath="$(ls | grep "^1920x1080" | shuf -n 1)" }

source4()   {  '/home/ds/Documents/scripts/Untitled Document 3.sh' && imgpath="$(ls | grep "^unsplashimg")" }

SOURCES=("source2" "source3" "source4")
$(eval $(shuf -n1 -e "${SOURCES[@]}"))
echo $imgpath

The bash script part runs, but the part after && does not and hence echo $imgpath gives no output. When I run individual commands like

'/home/ds/Documents/scripts/Untitled Document 1.sh' && imgpath="$(ls | grep "^unsplash")"

then I get desired outputs.

What am I doing wrong?

I have taken hints from


1 Answer 1


Syntax issues aside, it's how you're calling eval:

$(eval $(shuf -n1 -e "${SOURCES[@]}"))

The outer $(...) mean that the eval happens inside a subshell, then the current shell takes the output and executes that as a command.

Because eval runs in a subshell, the contents of the variable will disappear with the subshell.

Now, do you need eval? The shuf command will produce a string with the same name as a function. You could write instead:

func=$(shuf -n1 -e "${SOURCES[@]}") && "$func"

or simply

$(shuf -n1 -e "${SOURCES[@]}")

In the last case, we do want the shell to execute the output of shuf as a command

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .