Dialog in bash is not grabbing variables correctly
You can use that method to capture dialog otput directly into variable:
exec 3>&1
result=$(dialog --menu head 15 20 6 $(for ((i=1;i<30;i++));do echo tag$i item$i;done) 2>&1 1>&3);
exitcode=$?;
exec 3>&-;
echo $result $exitcode
http://mywiki.wooledge.org/BashFAQ/002
so with my approach startup
will look like:
startup()
{
exec 3>&1
_return=$(dialog --menu "Tiers are currently set as the following. Which would you like to update? \n" 12 78 5 \
"Stable" "$(cat ${DIR}/.tiers|grep Stable|sed 's/Stable=//g')" "Release" "$(cat ${DIR}/.tiers|grep Release|sed 's/Release=//g')" "Beta" "$(cat ${DIR}/.tiers|grep Beta|sed 's/Beta=//g')" 2>&1 1>&3)
exitcode=$?
exec 3>&-;
# OK is pressed
if [ "$exitcode" == "0" ] ; then
if [[ "$_return" == "Stable" || "$_return" == "Release" || "$_return" == "Beta" ]]
then
stable
fi
fi
echo "You have now exited the application"
clean_up;
}
additionaly many unclean things like $(${VERSION}) here:
dialog --msgbox "WARNING!!!!\n\n The folder $(${VERSION}) does not
as i understand from code it will run empty command as .version is empty on startup and
VERSION=`cat .version`
in tier_update_prompt()
$VERSION still empty string,
I tried to refactory your code, but it turn that it messed to much so suggestions:
- get dialog results as i shown above
- run functions with parameters:
#declaration
function_name() {
parameter=$1;
echo "$parameter"
}
var=value
#run function
function_name var
- do not overcomplexity with ${VAR},
- remember that double quotes expands, so
echo "here is $var"
instead ofecho "here is $(echo ${var})"
- use as less temporary files as you can for example:
diff <(ls dir1) <(ls dir2)
- do not keep working files in root directory (like /test/)
- do not work as root
- learn perl
How to return the result of a dialog question in a bash function
When you run dialog
in command substitution $()
, the stdout is not terminal any more.
You need to pass it to dialog
:
#!/usr/bin/env bash
function BUL_askYesNo()
{
exec 3>&1
return $(dialog --yesno "$1" 0 0 2>&1 1>&3)
}
BUL_askYesNo Hello
But return
is still not working. I think this is much simpler :
#!/usr/bin/env bash
function BUL_askYesNo()
{
dialog --yesno "$1" 0 0
}
BUL_askYesNo Hello
BASH: Dialog input in a variable
Basically you will use command substitution to obtain the output of a command into a variable. Like this:
date=$(date)
which writes the output of the date
command to the variable $date
.
But if we try the same with the dialog dialog
command:
user_input=$(dialog --title "Create Directory" --inputbox "Enter the directory name:" 8 40)
we get an empty screen! Why does this happen?
Explanation:
dialog
outputs the user input on stderr, since stdout will already being used by ncurses to update the screen. Without output redirection being used, the command substitution will return the command's stdout into the variable - meaning the output of ncurses will not get printed on screen. However if you type something (you can't see anything while typing):
test<enter>
The text test
will appear on screen. This happens because it will been written to stderr and stderr still points to the current terminal.
Note: You might expect the ncurses output in $user_input
but $user_input
is empty after the command. I assume that this happens because dialog
will check if it's output is going to a tty and it won't output anything otherwise. (Haven't verfied that)
Solution:
We can exchange stderr and stdout using i/o rerouting. We will turn stderr into stdout and write the user input to the variable but on the other hand turn stdout into stderr which will make ncurses outputting to the screen:
3>&1 1>&2 2>&3 3>&-
In short: 3>&1
opens a new file descriptor which points to stdout, 1>&2
redirects stdout to stderr, 2>&3
points stderr to stdout and 3>&-
deletes the files descriptor 3
after the command has been executed.
This gives us the final command:
user_input=$(\
dialog --title "Create Directory" \
--inputbox "Enter the directory name:" 8 40 \
3>&1 1>&2 2>&3 3>&- \
)
mkdir "$user_input"
Parsing output of chained dialog
exec 3>&1
result=$( dialog --clear --title title --menu Choose: 20 70 4 1 a 2 b 3 c \
--and-widget --menu Choose: 20 70 4 1 x 2 y 3 z 2>&1 1>&3 )
exitcode=$?
exec 3>&-
echo "result = >$result<" "exit-code = >$exitcode<"
sep=$(echo -e "\t") # define the separator
x=${result%$sep*} # remove up from separator
y=${result#*$sep} # remove up to separator
echo "Choosen: x=$x y=$y"
See https://askubuntu.com/questions/491509/how-to-get-dialog-box-input-directed-to-a-variable for getting the result of dialog into a variable. Your code x=$((
indicates and arithmetic expansion, which is not properly finished. See man bash
$((expression))
Why it doesn't end with an error is beyond me. The quotes around dialogs parameters result in 5 parameters, while you need 4 parameters plus one or more pairs of parameters.
The result string from dialog seems to be separated by a TAB. Working with a regex based on blank would not work.
sed
is not needed, it can be done with (bash builtin) 'Parameter Expansion'.
The menu is still printed on stdout. exec 3>&1
creates a duplicate of stdout. 1>&3
directs the usual output to channel 3, which is a duplicate of 1. Normal output ends up in stdout.
2>&1
redirects stderr to stdout which ends up as content of the variable.
In case of an error the error message is in your variable. Some error handling is needed.
Could not test with Xdialog, but I would expect it to work too.
Capture both stdout and stderr in Bash
There is no way to capture both without temp file.
You can capture stderr to variable and pass stdout to user screen (sample from here):
exec 3>&1 # Save the place that stdout (1) points to.
output=$(command 2>&1 1>&3) # Run command. stderr is captured.
exec 3>&- # Close FD #3.
# Or this alternative, which captures stderr, letting stdout through:
{ output=$(command 2>&1 1>&3-) ;} 3>&1
But there is no way to capture both stdout and stderr:
What you cannot do is capture stdout in one variable, and stderr in another, using only FD redirections. You must use a temporary file (or a named pipe) to achieve that one.
How to store standard error in a variable
It would be neater to capture the error file thus:
ERROR=$(</tmp/Error)
The shell recognizes this and doesn't have to run 'cat
' to get the data.
The bigger question is hard. I don't think there's an easy way to do it. You'd have to build the entire pipeline into the sub-shell, eventually sending its final standard output to a file, so that you can redirect the errors to standard output.
ERROR=$( { ./useless.sh | sed s/Output/Useless/ > outfile; } 2>&1 )
Note that the semi-colon is needed (in classic shells - Bourne, Korn - for sure; probably in Bash too). The '{}
' does I/O redirection over the enclosed commands. As written, it would capture errors from sed
too.
WARNING: Formally untested code - use at own risk.
Variable as multiple command parameters ignore quotes in Bash
After parameter expansion, any quotes in the result are treated as literal characters, not syntax for escaping whitespace. The correct way to create a list of values is to use an array, which acts as a second layer of quoting to allow whitespace in each element. As a bonus, array assignments also allow for more readable formatting.
MAIN_MENU=(
1 'Create new image' # Comments can be added, as well
2 'Start image as overriding'
3 'Start image as snapshot'
4 'Install OS'
5 'Settings'
)
dialog --title "Title" --menu 'Choose operation:' 0 0 5 "${MAIN_MENU[@]}"
Why does my menu with select fail the first time?
This problem only occurs when you type the commands interactively, not in a script. The reason is that the line you type after the select
line is being used as the response to the prompt. Since if
isn't in the menu, it reports an error. Then it doesn't execute the if
command, because it was read as the response to the prompt.
It's not a problem in a script because the commands in the script are not used as standard input.
Related Topics
Find Is Returning "Find: .: Permission Denied", But I Am Not Searching In
Is There Any Difference Between '=' and '==' Operators in Bash or Sh
Linux - Run Android Emulator on Nouveau Driver
How to Modify The Linux Kernel to Change The Version String That Uname Returns
Add a Directory When Creating Tar Archive
Remove Strings by a Specific Delimiter
Cython Standalone Executable on Ubuntu
Bash Script with User Defined Functions in Autocomplete
Go Memory Leak When Doing Concurrent Os/Exec.Command.Wait()
How to Concatenate Svg Files Lengthwise from Linux Command Line
How to Run an Image Windows Docker on Ubuntu
Alpine Linux: Pmap Output Not Showing Rss
How to Open The Default Text Editor in Linux
X11 Forwarding Through Google Colab
How to Change The Desktop Wallpaper on Linux from Within a Shell/Bash Script
Raspberry Pi: Spi Not Working, Spi_Bcm2835 Not Showing with Lsmod