Last active
July 12, 2026 20:06
-
-
Save hsandt/113d3c6698a54e378d44b5024140c2a0 to your computer and use it in GitHub Desktop.
Install Godot 3 stable or 4 beta, rc or stable and create desktop entry for Windows or Linux
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| [Desktop Entry] | |
| Name=Godot Engine $VERSION $CHANNEL | |
| GenericName=Libre game engine | |
| Comment=Multi-platform 2D and 3D game engine with a feature-rich editor | |
| Exec=godot$VERSION_$CHANNEL %f | |
| Icon=$HOME/.local/share/applications/godot.png | |
| Terminal=false | |
| Type=Application | |
| MimeType=application/x-godot-project; | |
| Categories=Development;IDE; | |
| Name[en_US]=Godot $VERSION $CHANNEL.desktop |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| # Gist: https://gist.github.com/hsandt/113d3c6698a54e378d44b5024140c2a0 | |
| # CONFIG: customize to match your needs | |
| default_base_install_folder="${HOME}/Applications/Game Engines/Godot" | |
| usage() { | |
| echo "Usage: install_godot_and_create_desktop_entry.sh <version> <channel> | |
| Install a version of Godot for Linux or Windows 64-bit in Godot path | |
| (default '${HOME}/Applications/Game Engines/Godot/'). | |
| You may customize Godot path by adding a file 'godot_path.txt' in the bin directory | |
| (Linux: '${HOME}/.local/bin', Windows: '$HOME/bin') | |
| containing the path to your install folder of choice. | |
| On Linux, also create a .desktop launcher for it. | |
| On Windows, also installs the '_console.exe' binary variant, which opens a terminal besides the application. | |
| Requirements: | |
| - perl installed | |
| - Linux: \"Godot template.desktop\" placed in the same directory as this script | |
| - Linux: Godot icon placed at ~/.local/share/applications/godot.png | |
| - jq installed (https://jqlang.org/) if using --latest option | |
| (for Windows, see https://stackoverflow.com/questions/53967693/how-to-run-jq-from-gitbash-in-windows) | |
| - Windows: '$HOME/bin' must be in your Git Bash PATH | |
| ARGUMENTS | |
| version Version of godot to download. Do not include channel like 'beta' here. | |
| Ex: '4.0.1'. | |
| channel Channel of godot to download, including number, excluding mono (see option -m instead). | |
| Ex: 'beta14', 'rc1', 'stable' | |
| -m, --mono Download mono build | |
| -l, --latest Show latest version available on Godot repository and quit | |
| -h, --help Show this help and quit | |
| " | |
| } | |
| show_latest() { | |
| # Use CLI to get latest release on GitHub: https://stackoverflow.com/questions/34899736/how-can-i-use-git-cli-to-get-the-latest-release | |
| # Parsing JSON with Unix tools: https://stackoverflow.com/questions/1955505/parsing-json-with-unix-tools | |
| # Requires jq (https://jqlang.org/) | |
| if hash jq 2> /dev/null; then | |
| latest_version_with_quotes=`curl -s https://api.github.com/repos/godotengine/godot/releases/latest | jq .name` | |
| # Remove surrounding quotes: https://stackoverflow.com/questions/9733338/shell-script-remove-first-and-last-quote-from-a-variable | |
| latest_version="${latest_version_with_quotes%\"}" | |
| latest_version="${latest_version#\"}" | |
| echo "$latest_version" | |
| else | |
| echo "ERROR: no jq, cannot read JSON data" | |
| success=false | |
| fi | |
| } | |
| # Default arguments | |
| mono=false | |
| # Read arguments | |
| positional_args=() | |
| while [[ $# -gt 0 ]]; do | |
| case $1 in | |
| -h | --help ) | |
| usage | |
| exit 0 | |
| ;; | |
| -l | --latest ) | |
| show_latest | |
| exit 0 | |
| ;; | |
| -m | --mono ) | |
| mono=true | |
| shift # past argument | |
| ;; | |
| -* ) # unknown option | |
| echo "Unknown option: '$1'" | |
| usage | |
| exit 1 | |
| ;; | |
| * ) # store positional argument for later | |
| positional_args+=("$1") | |
| shift # past argument | |
| ;; | |
| esac | |
| done | |
| if ! [[ ${#positional_args[@]} -eq 2 ]]; then | |
| echo "Wrong number of positional arguments: found $#, expected 2." | |
| echo "Passed positional arguments: $@" | |
| usage | |
| exit 1 | |
| fi | |
| version="${positional_args[0]}" | |
| channel="${positional_args[1]}" | |
| parent_dir_path="$(dirname "$0")" | |
| # https://stackoverflow.com/questions/394230/how-to-detect-the-os-from-a-bash-script | |
| if [[ "$OSTYPE" == "linux-gnu"* ]]; then | |
| # Linux | |
| if [[ "$version" == 3* ]]; then | |
| # Godot 3 was naming "X11" the Linux build | |
| platform_suffix="x11_64" | |
| binary_suffix="x11.64" | |
| if [[ "$mono" == true ]]; then | |
| zip_suffix="x11_64" | |
| else | |
| zip_suffix="x11.64" | |
| fi | |
| else | |
| platform_suffix="linux_x86_64" | |
| binary_suffix="linux.x86_64" | |
| if [[ "$mono" == true ]]; then | |
| zip_suffix="linux_x86_64" | |
| else | |
| zip_suffix="linux.x86_64" | |
| fi | |
| fi | |
| elif [[ "$OSTYPE" == "cygwin" || "$OSTYPE" == "msys" ]]; then | |
| # Windows, either: | |
| # - using Cygwin (POSIX compatibility layer and Linux environment emulation for Windows) | |
| # - using MSYS (Lightweight shell and GNU utilities compiled for Windows), itself part of MinGW, itself used by Git Bash | |
| platform_suffix="win64" | |
| binary_suffix="win64.exe" | |
| if [[ "$mono" == true ]]; then | |
| zip_suffix="win64" | |
| else | |
| zip_suffix="win64.exe" | |
| fi | |
| else | |
| echo "Unsupported platform '$OSTYPE'. STOP." | |
| exit 1 | |
| fi | |
| if [[ "$mono" == true ]]; then | |
| full_channel="${channel}_mono" | |
| else | |
| full_channel="${channel}" | |
| fi | |
| # Non-mono build example: "Godot_v4.2.2-stable_linux_x86_64", "Godot_v4.2.2-stable_win64.exe" | |
| # Mono build example: "Godot_v4.2.2-stable_mono_linux_x86_64", "Godot_v4.2.2-stable_mono_win64" | |
| godot_zip_basename="Godot_v${version}-${full_channel}_${zip_suffix}" | |
| godot_zip_name="${godot_zip_basename}.zip" | |
| godot_install_dir_name="Godot_v${version}-${full_channel}_${platform_suffix}" | |
| godot_bin_name="Godot_v${version}-${full_channel}_${binary_suffix}" | |
| # Remove existing archive if any (in case it was previously incorrectly downloaded) | |
| rm -f "$godot_zip_name" | |
| if [[ "$channel" == "stable"* ]]; then | |
| # Stable releases are on GitHub | |
| # Note that the directory never contains "mono", so we use channel instead of full_channel | |
| # but we use full_channel for the actual zip | |
| download_url="https://github.com/godotengine/godot/releases/download/${version}-${channel}/${godot_zip_name}" | |
| elif [[ "$channel" == "dev"* ]]; then | |
| # Dev releases are on GitHub with a slightly different directory name, godot-builds | |
| download_url="https://github.com/godotengine/godot-builds/releases/download/${version}-${channel}/${godot_zip_name}" | |
| else | |
| # Release candidates are on Tux Family | |
| # Note that the directory never contains "mono", so we use channel instead of full_channel | |
| download_url="https://downloads.tuxfamily.org/godotengine/${version}/${channel}/${godot_zip_name}" | |
| fi | |
| # Download archive for passed version in current folder | |
| # We prefer curl (-L follow redirect, important on GitHub releases, -O output file with same name) | |
| # to wget so Windows users don't need to install wget on Windows | |
| curl -LO "$download_url" | |
| if [[ "$mono" == true ]]; then | |
| # Mono zip already contains a wrapping directory (named like zip basename), | |
| # which contains binary + GodotSharp directory, so just unzip in the wild | |
| unzip "$godot_zip_name" | |
| else | |
| # Non-mono zip contains wild files: the binary and, on Windows, the '_console.exe' binary variant | |
| # Since there are multiple files on Windows, it's easier to keep extract files under a directory | |
| # to move them together later (and on Linux it will just prepare a sub-folder containing 1 file | |
| # for the final installation) | |
| # so unzip to folder named like zip basename | |
| unzip "$godot_zip_name" -d "$godot_install_dir_name" | |
| fi | |
| # Remove archive to clean up current folder | |
| rm "$godot_zip_name" | |
| if [[ "$OSTYPE" == "linux-gnu"* ]]; then | |
| bin_dir_path="${HOME}/.local/bin" | |
| elif [[ "$OSTYPE" == "cygwin" || "$OSTYPE" == "msys" ]]; then | |
| bin_dir_path="${HOME}/bin" | |
| else | |
| echo "Unsupported platform '$OSTYPE'. STOP." | |
| exit 1 | |
| fi | |
| # Create bin directory if needed | |
| mkdir -p "$bin_dir_path" | |
| # Set base install folder to use: | |
| # - read godot_path.txt if present | |
| # - use default path else | |
| if [[ -f "${bin_dir_path}/godot_path.txt" ]]; then | |
| base_install_folder=`cat "${bin_dir_path}/godot_path.txt"` | |
| echo "Found '${bin_dir_path}/godot_path.txt', installing Godot in '$base_install_folder'..." | |
| else | |
| base_install_folder="$default_base_install_folder" | |
| echo "No '${bin_dir_path}/godot_path.txt', installing Godot in default location '$base_install_folder'..." | |
| fi | |
| binary_install_folder="$base_install_folder/$godot_install_dir_name" | |
| # Delete any previous installation to be clean, then move the unzipped archive folder to target path | |
| rm -rf "$binary_install_folder" | |
| mkdir -p "$base_install_folder" | |
| # The unzipped archive folder already has the target folder name so just move it to the *parent* folder | |
| mv -f "$godot_install_dir_name" "$base_install_folder" | |
| echo "Installed '${godot_install_dir_name}' folder in '${base_install_folder}/'" | |
| if [[ "$OSTYPE" == "linux-gnu"* ]]; then | |
| # Create symbolic link for terminal and future Desktop entry (overwrites any existing link) | |
| install_path="${binary_install_folder}/${godot_bin_name}" | |
| symlink_path="${bin_dir_path}/godot${version}_${full_channel}" | |
| ln -sf "$install_path" "$symlink_path" | |
| echo "Created symbolic link at '$symlink_path'" | |
| # Create Desktop entry from template (overwrites any existing file) | |
| desktop_entry_path="${HOME}/.local/share/applications/Godot ${version} ${full_channel}.desktop" | |
| cp "${parent_dir_path}/Godot template.desktop" "$desktop_entry_path" | |
| # https://stackoverflow.com/questions/6994947/how-to-replace-a-string-in-an-existing-file-in-perl | |
| perl -pi -e "s/\\\$VERSION/${version}/g" "$desktop_entry_path" | |
| perl -pi -e "s/\\\$CHANNEL/${full_channel}/g" "$desktop_entry_path" | |
| # https://stackoverflow.com/questions/26080096/installed-desktop-file-to-have-users-home-directory-path-inserted | |
| # mind the comma separator since we deal with paths containing slashes | |
| # note that "~" doesn't work with Icon=, we need full path expansion | |
| perl -pi -e "s,\\\$HOME,${HOME},g" "$desktop_entry_path" | |
| echo "Created desktop entry at '$desktop_entry_path'" | |
| elif [[ "$OSTYPE" == "cygwin" || "$OSTYPE" == "msys" ]]; then | |
| # Create symbolic link for terminal (overwrites any existing link) | |
| install_path="${binary_install_folder}/${godot_bin_name}" | |
| # On Windows we just use "$HOME/bin" to simplify, but make sure it is in your Git Bash PATH | |
| symlink_path="${bin_dir_path}/godot${version}_${full_channel}.exe" | |
| ln -sf "$install_path" "$symlink_path" | |
| if [[ $? -ne 0 ]]; then | |
| echo "$conversion_info" | tee -a "$conversion_log_filename" | |
| echo "Creating symlink of '$install_path' at '$symlink_path' failed, STOP." | |
| exit 1 | |
| fi | |
| echo "Created symbolic link at '$symlink_path'" | |
| else | |
| echo "Unsupported platform '$OSTYPE'. STOP." | |
| exit 1 | |
| fi |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| # The opposite operation of install_godot_and_create_desktop_entry.sh | |
| # Gist: https://gist.github.com/hsandt/113d3c6698a54e378d44b5024140c2a0 | |
| # CONFIG: customize to match your needs | |
| base_install_folder="${HOME}/Applications/Game Engines/Godot" | |
| usage() { | |
| echo "Usage: uninstall_godot_and_create_desktop_entry.sh version channel | |
| Uninstall a version of Godot for Linux installed in ${HOME}/Applications/Game Engines/Godot/ and | |
| remove the .desktop launcher for it. | |
| Requirements: | |
| - perl installed | |
| - the Godot version to remove must have been installed with install_godot_and_create_desktop_entry.sh | |
| (or using the same path conventions) | |
| ARGUMENTS | |
| version Version of godot to uninstall. Do not include channel like 'beta' here. | |
| Ex: '4.0.1'. | |
| channel Channel of godot to uninstall, including number, excluding mono (see option -m instead). | |
| Ex: 'beta14', 'rc1', 'stable' | |
| -m Uninstall mono build | |
| " | |
| } | |
| # Default arguments | |
| mono=false | |
| # Read arguments | |
| positional_args=() | |
| while [[ $# -gt 0 ]]; do | |
| case $1 in | |
| -h | --help ) | |
| usage | |
| exit 0 | |
| ;; | |
| -m | --mono ) | |
| mono=true | |
| shift # past argument | |
| ;; | |
| -* ) # unknown option | |
| echo "Unknown option: '$1'" | |
| usage | |
| exit 1 | |
| ;; | |
| * ) # store positional argument for later | |
| positional_args+=("$1") | |
| shift # past argument | |
| ;; | |
| esac | |
| done | |
| if ! [[ ${#positional_args[@]} -eq 2 ]]; then | |
| echo "Wrong number of positional arguments: found $#, expected 2." | |
| echo "Passed positional arguments: $@" | |
| usage | |
| exit 1 | |
| fi | |
| version="${positional_args[0]}" | |
| channel="${positional_args[1]}" | |
| if [[ "$version" == 3* ]]; then | |
| # Godot 3 was naming "X11" the Linux build | |
| binary_linux_suffix="x11.64" | |
| if [[ "$mono" == true ]]; then | |
| zip_linux_suffix="x11_64" | |
| else | |
| zip_linux_suffix="x11.64" | |
| fi | |
| else | |
| binary_linux_suffix="linux.x86_64" | |
| if [[ "$mono" == true ]]; then | |
| zip_linux_suffix="linux_x86_64" | |
| else | |
| zip_linux_suffix="linux.x86_64" | |
| fi | |
| fi | |
| if [[ "$mono" == true ]]; then | |
| full_channel="${channel}_mono" | |
| else | |
| full_channel="${channel}" | |
| fi | |
| # Non-mono build example: "Godot_v4.2.2-stable_linux_x86_64" | |
| # Mono build example: "Godot_v4.2.2-stable_mono_linux_x86_64" | |
| godot_zip_basename="Godot_v${version}-${full_channel}_${zip_linux_suffix}" | |
| godot_bin_name="Godot_v${version}-${full_channel}_${binary_linux_suffix}" | |
| if [[ "$mono" == true ]]; then | |
| # Move the whole directory (named like zip basename), which contains binary + GodotSharp directory, under the install folder | |
| binary_install_folder="$base_install_folder/$godot_zip_basename" | |
| else | |
| # Non-mono build: we should have extracted a single file named "$godot_bin_name" | |
| # Move it to the target folder (overwrites any existing file) | |
| binary_install_folder="$base_install_folder" | |
| fi | |
| install_path="${binary_install_folder}/${godot_bin_name}" | |
| if [[ -f "$install_path" ]]; then | |
| rm "$install_path" | |
| echo "Removed Godot binary at $install_path" | |
| else | |
| echo "No file at '$install_path', so nothing to remove" | |
| fi | |
| symlink_path="${HOME}/.local/bin/godot${version}_${full_channel}" | |
| if [[ -L "$symlink_path" ]]; then | |
| rm "$symlink_path" | |
| echo "Removed symlink at $symlink_path" | |
| else | |
| echo "No symlink at '$symlink_path', so nothing to remove" | |
| fi | |
| desktop_entry_path="${HOME}/.local/share/applications/Godot ${version} ${full_channel}.desktop" | |
| if [[ -f "$desktop_entry_path" ]]; then | |
| rm "$desktop_entry_path" | |
| echo "Removed desktop entry at ${desktop_entry_path}" | |
| else | |
| echo "No file at '$desktop_entry_path', so nothing to remove" | |
| fi |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I added an uninstall script to revert the operations of the install script. Convenient to remove older versions of Godot, esp. dev and rc.