I've written a script with a while loop, not realising the difficulty of getting a variable out of said while loop.
What I want to do is to run the command the while loop saves in the 'stream' variable (see code below) after the while loop has completed as many loops as needed. I'm using this script to detect which game controllers are connected and creating a command to initialize moonlight, a program for the raspberry pi which lets me stream through Nvidia Game Stream, with different controller types.
#!/bin/bash
stream="moonlight stream -1080 -app Steam"
device=none
event=0
Player="-input /dev/input/event"
XbElite="-mapping /opt/retropie/configs/moonlight/XboxOne.map"
PlSt3="-mapping /opt/retropie/configs/moonlight/PS3.map"
XboxElite="N\:\ Name\=\"Microsoft\ X\-Box\ One\ Elite\ pad\""
PS3="N\:\ Name\=\"PLAYSTATION\(R\)3\ Controller\""
cat /proc/bus/input/devices | \
while read CMD; do
line=$(echo "$CMD" | sed 's/ /\\ /g; s/:/\\:/g; s/(/\\(/g; s/)/\\)/g; s/-/\\-/g; s/=/\\=/g')
if [ "$line" = "$XboxElite" ]; then
echo Xbox
device=xboxElite
if [ "$device" = "xboxElite" ]; then
stream="$stream $XbElite $Player$event"
event=$((event+1))
device=none
fi
elif [ "$line" = "$PS3" ]; then
echo PS3
device=ps3
if [ "$device" = "ps3" ]; then
stream="$stream $PlSt3 $Player$event"
event=$((event+1))
device=none
fi
fi
done
echo $stream #put here as a placeholder to see the final command in the variable. Currently printing: 'moonlight stream -1080 -app Steam'
I realise this probably isn't the cleanest way of doing this or that the code is even close to as well written as it could be, but as I have little previous experience with coding of any sort, this is what I could manage for the time being.
Any help would be greatly appreciated!
Well, the way to run it as a command would be to just remove the
echo:... except that you can't, because the
whileloop is on the right side of a pipe. That means it runs in a "subshell" and can't have side effects back in its parent shell (outside of the loop); after the loop exits,$streamwill be back to what it was before the loop.In order to keep the loop in the same environment as the surrounding code instead of its own subshell, you need to read from the file directly rather than using a pipe:
In the general case, when building a command dynamically to run later, you are going to run into problems with quoting or spaces or other special characters. It's easiest to avoid those issues if you build the command in an array instead of a string. The syntax for building and running a command inside an array looks like this: