Zenity lets a shell script show simple graphical dialogs—such as confirmations, text fields, and file pickers—without building a full desktop application. Dialogs that collect information print it to standard output; buttons and failures are reported through exit status. That distinction is the key to writing scripts that handle input, Cancel, and errors reliably.
Zenity needs access to a graphical desktop session, so it is designed for interactive desktop automation, not unattended jobs on a headless server. Its options and appearance can also vary by installed release and desktop environment.
What Zenity does—and when to use it
Zenity is a command-line utility that displays predefined GTK dialogs from shell scripts. It can add a simple graphical front end to an existing command-line task: ask before deleting files, collect a directory, show a status message, or present a short list of actions. See the Zenity manual for its documented dialog types and options.
It is a good fit when the work is already handled by shell commands and only a few prompts are needed. It is not a general-purpose GUI toolkit: choose a full GTK, Qt, or libadwaita application for complex layouts, many states, persistent application data, or extensive validation. Use a terminal interface instead when the workflow must run without a desktop.
Recommended Free Tools
#1 Best Overall
Install Zenity and verify your version
Install the package provided by your distribution. These examples apply to common distribution families; package availability and versions depend on the release and configured repositories.
# Debian or Ubuntu family
sudo apt update
sudo apt install zenity
# Fedora family
sudo dnf install zenity
# Arch family
sudo pacman -S zenity
Then check that the executable is available and inspect the options supported by your local build:
command -v zenity
zenity --version
zenity --help
zenity --help-all
For package-specific diagnostics, use the command for your distribution:
type -a zenity
dpkg -s zenity 2>/dev/null # Debian/Ubuntu
rpm -q zenity 2>/dev/null # Fedora/RHEL
pacman -Qi zenity 2>/dev/null # Arch
Test a basic dialog from the same account and desktop session that will run the script:
Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minutePC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11zenity --info --title="Zenity test" --text="Zenity is working."
Zenity releases and GTK dependencies are not uniform across Linux. Debian stable package metadata lists a 4.x package with GTK 4 dependencies, while Ubuntu publishes manuals for both Zenity 3.32.0 and 4.1.99. These are examples of release differences, not a claim that every system uses either version. See Debian’s stable package metadata, the Ubuntu Focal manual, and the Ubuntu Questing manual. Check local help or man zenity before relying on an advanced option.
Understand standard output and exit status
Zenity uses two result channels. An input dialog writes the submitted value to standard output, which command substitution can capture. A question dialog reports the button choice through its exit status. Capture or test the status immediately; another command can overwrite $?.
Capture a text entry
name=$(zenity --entry
--title="Name"
--text="Enter your name:")
status=$?
if [ "$status" -ne 0 ]; then
printf '%sn' "Input cancelled or dialog failed" >&2
exit 1
fi
printf 'Hello, %sn' "$name"
A successful submission can still contain an empty string. Treat cancellation, an empty value, and malformed input as separate cases; validate the value before using it.
Handle a question
if zenity --question
--title="Continue?"
--text="Proceed with the operation?"; then
echo "User selected OK"
else
echo "User selected Cancel or the dialog failed"
fi
If your script must distinguish cancellation, timeout, and other failures, save the status and handle documented values deliberately:
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Fix the driver behind crashes, sound loss and screen glitches3Clear out junk files and repair common Windows errorszenity --question --text="Delete this file?"
status=$?
case "$status" in
0) echo "Confirmed" ;;
1) echo "Cancelled" ;;
5) echo "Timed out" ;;
*) printf 'Zenity failed with status %sn' "$status" >&2 ;;
esac
Do not assume every release or dialog has identical status behavior. Consult the manual and test the installed version for the paths your script needs.
Show information, warnings, errors, and confirmations
Message dialogs display text and return when the user dismisses them. Question dialogs are the appropriate choice when an operation must wait for an explicit decision.
Information, warning, and error
zenity --info --title="Completed"
--text="The backup finished successfully."
zenity --warning --title="Warning"
--text="This operation may overwrite existing files."
zenity --error --title="Error"
--text="The backup could not be created."
Confirmation with meaningful button labels
if zenity --question
--title="Overwrite file?"
--text="A file with this name already exists."
--ok-label="Overwrite"
--cancel-label="Keep existing"; then
echo "Proceeding with overwrite"
else
echo "Keeping existing file"
fi
Button labels improve clarity but do not change the need to check the dialog’s status.
Collect and validate text or password input
Text fields
An entry dialog can provide a default value with --entry-text. Validate input in the script before passing it to another command.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
name=$(zenity --entry
--title="User name"
--text="Enter a non-empty name:"
--entry-text="guest")
status=$?
if [ "$status" -ne 0 ]; then
echo "Input cancelled" >&2
exit 1
fi
if [ -z "$name" ]; then
zenity --error --text="A name is required."
exit 1
fi
printf 'Entered: %sn' "$name"
Password fields
password=$(zenity --password --title="Authentication required")
status=$?
if [ "$status" -ne 0 ]; then
echo "Password entry cancelled" >&2
exit 1
fi
A password dialog is an input mechanism, not a secure credential store. Avoid printing or logging secrets, putting them in command-line arguments, or treating a shell variable as protected storage. For real credentials, use an established secret-management mechanism appropriate to the task.
Select files and directories
Choose an existing file
file=$(zenity --file-selection --title="Choose a file")
status=$?
if [ "$status" -ne 0 ]; then
echo "No file selected" >&2
exit 1
fi
if [ ! -f "$file" ]; then
zenity --error --text="The selected path is not a regular file."
exit 1
fi
printf 'Selected: %sn' "$file"
Choose a directory or save a file
directory=$(zenity --file-selection
--directory
--title="Choose a directory")
output=$(zenity --file-selection
--save
--confirm-overwrite
--title="Save report")
Check the exit status for these dialogs too before using the result. Options and behavior can differ by release; verify them with zenity --help-file-selection or the local manual.
Select multiple files
files=$(zenity --file-selection
--multiple
--separator=$'n'
--title="Choose files")
status=$?
if [ "$status" -ne 0 ]; then
echo "Selection cancelled" >&2
exit 1
fi
while IFS= read -r file; do
printf 'Selected: %sn' "$file"
done <<< "$files"
This newline-delimited approach is convenient, but Unix filenames can themselves contain newlines. Do not treat newline-separated output as a fully general representation of arbitrary paths. If your workflow must handle every valid filename, choose a data-transfer method and dialog interface that preserve path boundaries rather than assuming a text separator is unambiguous.
Present a list of actions
A list dialog can display rows and return the selected row. Keep the returned values stable if the script uses them to choose actions; avoid making a changeable display label your only internal identifier.
choice=$(printf '%sn'
"Backup home directory"
"Check disk space"
"Quit" |
zenity --list
--title="Choose an action"
--column="Action")
status=$?
if [ "$status" -ne 0 ]; then
exit 0
fi
case "$choice" in
"Backup home directory") echo "Starting backup" ;;
"Check disk space") df -h ;;
"Quit") exit 0 ;;
*) zenity --error --text="Unknown selection."; exit 1 ;;
esac
For multiple columns, provide matching column definitions and row data. For example:
zenity --list
--title="Processes"
--column="PID"
--column="Command"
1234 bash
5678 firefox
List output and multiple-selection behavior should be tested against your local release. Use a stable identifier column when the script needs to map a displayed choice to an action.
Rank #4
Build simple forms, calendar, and color prompts
Forms with multiple fields
result=$(zenity --forms
--title="Contact details"
--text="Enter contact information"
--add-entry="Name"
--add-entry="Email"
--separator="|")
status=$?
if [ "$status" -ne 0 ]; then
echo "Form cancelled" >&2
exit 1
fi
IFS='|' read -r name email <<< "$result"
printf 'Name: %snEmail: %sn' "$name" "$email"
Choose a separator that cannot occur in field values, or handle the output format more robustly if users may enter that character. Some releases also support password or calendar fields in forms; check local help for available options.
Calendar and color selection
date_value=$(zenity --calendar
--title="Choose a date"
--date-format="%Y-%m-%d")
color=$(zenity --color-selection
--title="Choose a color")
Date formatting and available options vary; verify the local calendar help rather than relying on an assumed default.
Show progress for a long-running task
A progress dialog reads updates from standard input. Send percentage values and, optionally, a message beginning with #:
{
echo "10"
echo "# Preparing..."
sleep 1
echo "40"
echo "# Copying files..."
sleep 1
echo "80"
echo "# Finishing..."
sleep 1
echo "100"
echo "# Complete"
} | zenity --progress
--title="Backup"
--percentage=0
--auto-close
For actual work, arrange for the task to report meaningful progress rather than displaying a percentage unrelated to its state. The bar is only a display: it does not automatically stop the underlying command when the user presses Cancel.
Understand pipeline status and cancellation
In Bash, PIPESTATUS records the status of each command in the most recent pipeline. Save it immediately, because another command replaces it.
for i in {1..100}; do
echo "$i"
echo "# Processing item $i"
sleep 0.05
done | zenity --progress
--title="Processing"
--percentage=0
--auto-close
--cancel-label="Stop"
statuses=("${PIPESTATUS[@]}")
producer_status=${statuses[0]}
zenity_status=${statuses[1]}
if [ "$zenity_status" -ne 0 ]; then
echo "Progress dialog was cancelled or failed" >&2
# Add explicit cleanup or worker termination here if required.
fi
This example uses Bash-specific syntax and illustrates status collection; a production script must explicitly arrange how the worker stops and cleans up on cancellation. Pipeline behavior, including what happens to a producer when the dialog closes, should be tested for the commands and shell used.
Free tools Windows power users keep installed
One-click scans. No signup required.
Best Value
Write safer Zenity scripts
- Quote variable expansions. Use
rm -- "$selected_file", notrm $selected_file. Quoting preserves spaces and prevents unintended word splitting or glob expansion. - Validate values before acting. Check that required input is present and that selected paths meet the task’s requirements.
- Avoid
eval. Never turn user input into shell code. Pass it as a quoted argument instead:grep -- "$pattern" "$file", noteval "grep $pattern $file". - Handle expected nonzero statuses explicitly. Cancellation is a normal path. With
set -e, commands that return nonzero can terminate a script unexpectedly if the control flow is not designed for them. Anifcondition often makes the intended handling clearer. - Separate GUI availability from task logic. If the dialog cannot open, report an actionable error or provide a deliberate non-GUI route where appropriate.
A common Bash starting point is set -o nounset and set -o pipefail; add set -o errexit only with care around expected failures such as Cancel and pipeline handling.
Handle display-session limitations
Zenity needs an accessible graphical session. It commonly fails when launched from cron, a system service, a container, an SSH session without graphical forwarding, or a root context that cannot access the logged-in user’s display. GTK’s runtime documentation describes environment considerations such as DISPLAY; the exact behavior also depends on session configuration. See GNOME’s GTK runtime documentation.
Inspect the context in which the script runs:
printf 'DISPLAY=%sn' "${DISPLAY-}"
printf 'WAYLAND_DISPLAY=%sn' "${WAYLAND_DISPLAY-}"
printf 'XDG_SESSION_TYPE=%sn' "${XDG_SESSION_TYPE-}"
zenity --info --text="Display test"
Run the test as the same user and from the same launch mechanism as the real script. Do not blindly set DISPLAY=:0 or copy authentication cookies: display addresses and authorization are session-specific. If the job is unattended, use a non-GUI workflow or deliberately integrate it with the user’s desktop session.
Adjust text and presentation carefully
Some Zenity dialogs interpret text as Pango markup. To show literal untrusted content, disable markup where the option is supported:
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Scan for outdated or missing drivers - takes under a minuteDriver Scan →zenity --error
--no-markup
--text="$message"
--no-wrap is available for controlling wrapping in supported dialogs, but sizing and rendering depend on the GTK release, desktop theme, and environment. Check local help for --no-markup, --no-wrap, and related options rather than assuming identical behavior across machines.
Quick Recap
Troubleshoot common problems
| Symptom | Likely cause | What to check |
|---|---|---|
zenity: command not found |
Zenity is not installed or is not on PATH. |
Install the distribution package and run command -v zenity. |
| No dialog appears | The process cannot access a graphical session. | Inspect DISPLAY, WAYLAND_DISPLAY, and the user or service context. |
| The script waits indefinitely | A dialog is waiting for input, or a pipeline stage is blocked. | Run the dialog directly and inspect the pipeline stages. |
| The captured value is empty | The user submitted an empty value, or the command failed. | Check exit status separately, then validate the value. |
| Cancel is treated as success | The script checks stdout but not the dialog status. | Test the status immediately after the dialog. |
| A list action targets the wrong item | The script relies on changeable display labels as identifiers. | Return or map a stable identifier. |
| Multiple selected paths parse incorrectly | A filename contains the chosen separator, including a newline. | Do not assume delimited text can represent every valid pathname. |
| The progress window closes but work continues | The dialog and worker process are not automatically coupled. | Implement explicit cancellation and process cleanup. |
| Text displays unexpectedly | The dialog interprets text as markup. | Use --no-markup where supported for literal text. |
| It works in a terminal but not in cron | Cron generally lacks the user’s graphical session. | Use a non-GUI workflow or a desktop-session trigger. |
| Options or appearance changed after an upgrade | The installed Zenity or GTK generation differs. | Check zenity --version and local help. |
Choose an alternative when Zenity is not the right fit
| Tool | Interface | Best fit |
|---|---|---|
| Zenity | GTK graphical dialogs | Small desktop shell scripts with a few prompts. |
| YAD | GTK graphical dialogs | Workflows that need controls or customization beyond Zenity; availability and behavior vary. |
| KDialog | KDE/Qt dialogs | Scripts where KDE Plasma integration is preferred. |
dialog or whiptail |
Terminal interface | SSH, TTY, server, or other headless workflows. |
| GTK, Qt, or libadwaita application | Full graphical application | Complex interfaces, persistent state, and a maintainable application rather than a script wrapper. |
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

